diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..ce81892 --- /dev/null +++ b/.env.sample @@ -0,0 +1 @@ +DATABASE_URL= diff --git a/Cargo.lock b/Cargo.lock index e4833d6..fbf2246 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,6 +19,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "actix-cors" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daa239b93927be1ff123eebada5a3ff23e89f0124ccb8609234e5103d5a5ae6d" +dependencies = [ + "actix-utils", + "actix-web", + "derive_more 2.0.1", + "futures-util", + "log", + "once_cell", + "smallvec", +] + [[package]] name = "actix-http" version = "3.9.0" @@ -35,12 +50,12 @@ dependencies = [ "brotli", "bytes", "bytestring", - "derive_more", + "derive_more 0.99.19", "encoding_rs", "flate2", "futures-core", - "h2", - "http", + "h2 0.3.26", + "http 0.2.12", "httparse", "httpdate", "itoa", @@ -76,7 +91,7 @@ checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" dependencies = [ "bytestring", "cfg-if", - "http", + "http 0.2.12", "regex", "regex-lite", "serde", @@ -151,7 +166,7 @@ dependencies = [ "bytestring", "cfg-if", "cookie", - "derive_more", + "derive_more 0.99.19", "encoding_rs", "futures-core", "futures-util", @@ -207,7 +222,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom", + "getrandom 0.2.15", "once_cell", "version_check", "zerocopy", @@ -252,6 +267,46 @@ dependencies = [ "libc", ] +[[package]] +name = "argon2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" +dependencies = [ + "base64ct", + "blake2", + "cpufeatures", + "password-hash", +] + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.4.0" @@ -270,7 +325,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -279,12 +334,27 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + [[package]] name = "bitflags" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -375,6 +445,7 @@ dependencies = [ "iana-time-zone", "js-sys", "num-traits", + "serde", "wasm-bindgen", "windows-link", ] @@ -396,6 +467,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -457,14 +538,49 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.5" +version = "3.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" +checksum = "46f93780a459b7d656ef7f071fe699c4d3d2cb201c4b24d085b6ddc505276e73" dependencies = [ "nix", "windows-sys 0.59.0", ] +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "deranged" version = "0.3.11" @@ -487,6 +603,60 @@ dependencies = [ "syn", ] +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "diesel" +version = "2.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a917a9209950404d5be011c81d081a2692a822f73c3d6af586f0cab5ff50f614" +dependencies = [ + "diesel_derives", + "libsqlite3-sys", + "time", +] + +[[package]] +name = "diesel_derives" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52841e97814f407b895d836fa0012091dff79c6268f39ad8155d384c21ae0d26" +dependencies = [ + "diesel_table_macro_syntax", + "dsl_auto_type", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "diesel_table_macro_syntax" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "209c735641a413bc68c4923a9d6ad4bcb3ca306b794edaa7eb0b3228a99ffb25" +dependencies = [ + "syn", +] + [[package]] name = "digest" version = "0.10.7" @@ -495,6 +665,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", + "subtle", ] [[package]] @@ -508,6 +679,30 @@ dependencies = [ "syn", ] +[[package]] +name = "docker" +version = "0.1.0" +dependencies = [ + "reqwest", + "serde", + "serde_json", + "tokio", +] + +[[package]] +name = "dsl_auto_type" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139ae9aca7527f85f26dd76483eb38533fd84bd571065da1739656ef71c5ff5b" +dependencies = [ + "darling", + "either", + "heck", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "either" version = "1.15.0" @@ -530,16 +725,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] -name = "fallible-iterator" -version = "0.3.0" +name = "errno" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] [[package]] -name = "fallible-streaming-iterator" -version = "0.1.9" +name = "fastrand" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "flate2" @@ -558,10 +757,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "foldhash" -version = "0.1.4" +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" @@ -572,6 +780,15 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", +] + [[package]] name = "futures-core" version = "0.3.31" @@ -600,6 +817,7 @@ dependencies = [ "futures-task", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -617,10 +835,24 @@ name = "getrandom" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", - "wasi", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] @@ -640,7 +872,26 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.3.1", "indexmap", "slab", "tokio", @@ -653,18 +904,12 @@ name = "hashbrown" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" -dependencies = [ - "foldhash", -] [[package]] -name = "hashlink" -version = "0.10.0" +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" -dependencies = [ - "hashbrown", -] +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "http" @@ -677,6 +922,40 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.3.1", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http 1.3.1", + "http-body", + "pin-project-lite", +] + [[package]] name = "httparse" version = "1.10.1" @@ -689,6 +968,77 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.11", + "http 1.3.1", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http 1.3.1", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.3.1", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + [[package]] name = "iana-time-zone" version = "0.1.61" @@ -830,6 +1180,12 @@ dependencies = [ "syn", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "1.0.3" @@ -867,6 +1223,12 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + [[package]] name = "itoa" version = "1.0.15" @@ -892,6 +1254,21 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonwebtoken" +version = "9.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" +dependencies = [ + "base64", + "js-sys", + "pem", + "ring", + "serde", + "serde_json", + "simple_asn1", +] + [[package]] name = "language-tags" version = "0.3.2" @@ -900,9 +1277,9 @@ checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" [[package]] name = "libc" -version = "0.2.170" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libsqlite3-sys" @@ -914,6 +1291,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + [[package]] name = "litemap" version = "0.7.5" @@ -982,15 +1365,32 @@ checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "nix" -version = "0.29.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ "bitflags", "cfg-if", @@ -1007,12 +1407,31 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -1037,6 +1456,50 @@ version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +[[package]] +name = "openssl" +version = "0.10.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "parking_lot" version = "0.12.3" @@ -1057,7 +1520,18 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core", + "subtle", ] [[package]] @@ -1066,6 +1540,16 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pem" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +dependencies = [ + "base64", + "serde", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -1123,6 +1607,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "rand" version = "0.8.5" @@ -1150,7 +1640,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.15", ] [[package]] @@ -1218,17 +1708,61 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] -name = "rusqlite" -version = "0.34.0" +name = "reqwest" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e34486da88d8e051c7c0e23c3f15fd806ea8546260aa2fec247e97242ec143" +checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" dependencies = [ - "bitflags", - "fallible-iterator", - "fallible-streaming-iterator", - "hashlink", - "libsqlite3-sys", - "smallvec", + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.4.11", + "http 1.3.1", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.15", + "libc", + "untrusted", + "windows-sys 0.52.0", ] [[package]] @@ -1246,6 +1780,61 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustls" +version = "0.23.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7160e3e10bf4535308537f3c4e1641468cd0e485175d6163087c0393c7d46643" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.20" @@ -1258,12 +1847,44 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "1.0.26" @@ -1302,6 +1923,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_qs" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd34f36fe4c5ba9654417139a9b3a20d2e1de6012ee678ad14d240c22c78d8d6" +dependencies = [ + "percent-encoding", + "serde", + "thiserror 1.0.69", +] + [[package]] name = "serde_spanned" version = "0.6.8" @@ -1349,6 +1981,18 @@ dependencies = [ "libc", ] +[[package]] +name = "simple_asn1" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" +dependencies = [ + "num-bigint", + "num-traits", + "thiserror 2.0.12", + "time", +] + [[package]] name = "slab" version = "0.4.9" @@ -1380,6 +2024,18 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "2.0.99" @@ -1391,6 +2047,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + [[package]] name = "synstructure" version = "0.13.1" @@ -1402,6 +2067,10 @@ dependencies = [ "syn", ] +[[package]] +name = "sysd" +version = "0.1.0" + [[package]] name = "sysinfo" version = "0.33.1" @@ -1416,19 +2085,213 @@ dependencies = [ "windows", ] +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +dependencies = [ + "fastrand", + "getrandom 0.3.3", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "teus" version = "0.1.0" +dependencies = [ + "ctrlc", + "tempfile", + "teus-api", + "teus-auth", + "teus-config", + "teus-database", + "teus-docker", + "teus-monitor", + "teus-services", + "teus-types", + "tokio", + "tokio-test", +] + +[[package]] +name = "teus-api" +version = "0.1.0" +dependencies = [ + "actix-cors", + "actix-web", + "sysinfo", + "teus-auth", + "teus-config", + "teus-database", + "teus-docker", + "teus-monitor", + "teus-services", + "teus-types", +] + +[[package]] +name = "teus-auth" +version = "0.1.0" dependencies = [ "actix-web", + "argon2", "chrono", - "ctrlc", - "rusqlite", + "diesel", + "jsonwebtoken", + "serde", + "teus-config", + "teus-database", + "teus-schema", + "teus-types", +] + +[[package]] +name = "teus-config" +version = "0.1.0" +dependencies = [ + "actix-web", + "diesel", + "serde", + "tempfile", + "teus-database", + "teus-schema", + "teus-types", + "toml", +] + +[[package]] +name = "teus-database" +version = "0.1.0" +dependencies = [ + "diesel", + "tempfile", + "teus-types", +] + +[[package]] +name = "teus-docker" +version = "0.1.0" +dependencies = [ + "actix-web", + "docker", "serde", + "serde_json", + "serde_qs", + "teus-types", + "tokio", +] + +[[package]] +name = "teus-monitor" +version = "0.1.0" +dependencies = [ + "chrono", + "diesel", + "serde", + "serde_json", "sysinfo", + "teus-database", + "teus-schema", + "teus-types", +] + +[[package]] +name = "teus-schema" +version = "0.1.0" +dependencies = [ + "diesel", +] + +[[package]] +name = "teus-services" +version = "0.1.0" +dependencies = [ + "actix-web", + "diesel", + "serde", + "serde_json", + "teus-auth", + "teus-database", + "teus-monitor", + "teus-schema", + "teus-types", +] + +[[package]] +name = "teus-types" +version = "0.1.0" +dependencies = [ + "chrono", + "serde", + "serde_json", + "tempfile", "toml", ] +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "time" version = "0.3.39" @@ -1484,9 +2347,65 @@ dependencies = [ "pin-project-lite", "signal-hook-registry", "socket2", + "tokio-macros", "windows-sys 0.52.0", ] +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-test" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2468baabc3311435b55dd935f702f42cd1b8abb7e754fb7dfb16bd36aa88f9f7" +dependencies = [ + "async-stream", + "bytes", + "futures-core", + "tokio", + "tokio-stream", +] + [[package]] name = "tokio-util" version = "0.7.13" @@ -1534,6 +2453,33 @@ dependencies = [ "winnow", ] +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + [[package]] name = "tracing" version = "0.1.41" @@ -1554,6 +2500,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "typenum" version = "1.18.0" @@ -1566,6 +2518,18 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.4" @@ -1601,12 +2565,30 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" version = "0.2.100" @@ -1633,6 +2615,19 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.100" @@ -1665,6 +2660,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1694,7 +2699,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" dependencies = [ "windows-core 0.57.0", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1703,7 +2708,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1714,8 +2719,8 @@ checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" dependencies = [ "windows-implement", "windows-interface", - "windows-result", - "windows-targets", + "windows-result 0.1.2", + "windows-targets 0.52.6", ] [[package]] @@ -1746,13 +2751,42 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" +[[package]] +name = "windows-registry" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" +dependencies = [ + "windows-result 0.3.1", + "windows-strings", + "windows-targets 0.53.2", +] + [[package]] name = "windows-result" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06374efe858fab7e4f881500e6e86ec8bc28f9462c47e5a9941a0142ad86b189" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +dependencies = [ + "windows-link", ] [[package]] @@ -1761,7 +2795,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1770,7 +2804,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1779,14 +2813,30 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -1795,48 +2845,96 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" version = "0.7.3" @@ -1846,6 +2944,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + [[package]] name = "write16" version = "1.0.0" @@ -1924,6 +3031,12 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + [[package]] name = "zerovec" version = "0.10.4" diff --git a/Cargo.toml b/Cargo.toml index 7a6e42c..bc27ee5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,44 @@ [workspace] -# This file is part of the Teus project. -members = ["crates/docker"] -# members = ["crates/docker", "crates/sysd"] # add this when sysd is in developing state +members = [ + ".", + "crates/teus-types", + "crates/teus-config", + "crates/teus-database", + "crates/teus-monitor", + "crates/teus-auth", + "crates/teus-api", + "crates/teus-services", + "crates/teus-docker", + "crates/sysd", +] default-members = ["."] +[workspace.dependencies] +serde = { version = "1.0", features = ["derive"] } +tokio = { version = "1", features = ["full"] } +chrono = { version = "0.4", features = ["serde"] } +diesel = { version = "2.2.0", features = [ + "sqlite", + "returning_clauses_for_sqlite_3_35", +] } +actix-web = "4.9" + +[dependencies] +teus-types = { path = "crates/teus-types" } +teus-config = { path = "crates/teus-config" } +teus-database = { path = "crates/teus-database" } +teus-monitor = { path = "crates/teus-monitor" } +teus-auth = { path = "crates/teus-auth" } +teus-api = { path = "crates/teus-api" } +teus-services = { path = "crates/teus-services" } +teus-docker = { path = "crates/teus-docker" } +tokio = { version = "1", features = ["full"] } +ctrlc = "3.4" + +[dev-dependencies] +tempfile = "3.8" +tokio-test = "0.4" + [package] name = "teus" version = "0.1.0" @@ -18,34 +53,12 @@ path = "teus/lib.rs" name = "teus" path = "./teus/main.rs" -[dependencies] # we need to clean something here -docker = { path = "crates/docker"} -diesel = { version = "2.2.0", features = ["sqlite", "returning_clauses_for_sqlite_3_35"] } -dotenvy = "0.15" -actix-cors = "0.7.0" -actix-web = "4.9.0" -chrono = "0.4.40" -ctrlc = "3.4.5" -derive_more = { version = "2.0.1", features = ["display", "error", "from"] } -jsonwebtoken = "9.3.1" -rusqlite = "0.34.0" -serde = { version = "1.0.218", features = ["derive"] } -serde_json = "1.0" -serde_qs = "0.13" -sysinfo = "0.33.1" -toml = "0.8.20" -argon2 = "0.5.3" - -[dev-dependencies] -tempfile = "3.8" -tokio-test = "0.4" - [profile.release] -opt-level = "z" # Optimize for size -lto = true # Enable link-time optimization -strip = true # Strip symbols from binary -panic = "abort" # Abort on panic instead of unwinding -codegen-units = 1 # Reduce parallel code generation units +opt-level = "z" # Optimize for size +lto = true # Enable link-time optimization +strip = true # Strip symbols from binary +panic = "abort" # Abort on panic instead of unwinding +codegen-units = 1 # Reduce parallel code generation units [target.x86_64-unknown-linux-musl] linker = "x86_64-linux-musl-gcc" diff --git a/README.md b/README.md index 181b215..f7fed5a 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,19 @@ [![Rust Teus CI](https://github.com/imggion/Teus/actions/workflows/rust.yml/badge.svg)](https://github.com/imggion/Teus/actions/workflows/rust.yml) +## ⚠️ Important Disclaimer + +**This software is currently under active development and is NOT ready for production use.** + +Please be aware that: +- The codebase is subject to frequent changes and breaking updates +- Features may be incomplete or unstable +- Database schemas and APIs may change without notice +- Security features may not be fully implemented or tested +- No guarantees are provided regarding data integrity or system stability +- Refactoring needed + + Teus is a lightweight system monitoring service written in Rust that collects and exposes system metrics through a REST API. ## Features diff --git a/crates/docker/src/docker.rs b/crates/docker/src/docker.rs index 0f21634..9ff7195 100644 --- a/crates/docker/src/docker.rs +++ b/crates/docker/src/docker.rs @@ -1257,15 +1257,17 @@ impl DockerClient { /// /// If `socket_path` is `None`, it defaults to the standard Unix socket path /// "/var/run/docker.sock". - pub fn new(socket_path: Option) -> Self { + pub fn new(socket_path: Option) -> Result { // If socket_path is Some(path), use it. // If socket_path is None, execute the closure to get the default path. let path = socket_path.unwrap_or_else(|| DOCKER_SOCK.to_string()); - DockerClient { - // We now pass the guaranteed-to-be-valid path to the builder - request_builder: TeusRequestBuilder::new(path, "localhost".to_string()) - .expect("Are you sure docker is up and running?"), + match TeusRequestBuilder::new(path, "localhost".to_string()) { + Ok(request_builder) => { + let client = DockerClient { request_builder }; + Ok(client) + } + Err(_) => Err(DockerError::Generic("Error accessing Docker".to_string())), } } @@ -1274,15 +1276,14 @@ impl DockerClient { where T: for<'de> Deserialize<'de>, { - // First, try to deserialize as the expected type + /* T deserialization */ match serde_json::from_str::(response) { Ok(data) => Ok(data), Err(_) => { - // If that fails, try to deserialize as a Docker error response match serde_json::from_str::(response) { Ok(error_response) => Err(DockerError::Generic(error_response.message)), Err(_) => { - // If both fail, return the raw response as a generic error + /* if both fail, return the raw response as a generic error */ Err(DockerError::Generic(format!( "Failed to parse Docker response: {}", response @@ -1338,6 +1339,19 @@ impl DockerClient { } } +/* this custom clone is needed because the docker client contains an UnixStream that is unique for safety purposes */ +impl Clone for DockerClient { + fn clone(&self) -> Self { + let socket_path = self.request_builder.socket.clone(); + let host = self.request_builder.host.clone(); + + match TeusRequestBuilder::new(socket_path, host) { + Ok(request_builder) => DockerClient { request_builder }, + Err(_) => panic!("Failed to clone DockerClient: could not establish new connection"), + } + } +} + mod tests { #[allow(unused_imports)] use super::*; @@ -1365,7 +1379,7 @@ mod tests { fn test_get_containers() { // Our test now calls the correct helper function automatically. let test_socket = get_test_socket_path(); - let mut client = DockerClient::new(test_socket); + let mut client = DockerClient::new(test_socket).unwrap(); println!("{:?}", client); let containers = client.get_containers(None).unwrap(); @@ -1377,7 +1391,7 @@ mod tests { fn test_get_version() { // Our test now calls the correct helper function automatically. let test_socket = get_test_socket_path(); - let mut client = DockerClient::new(test_socket); + let mut client = DockerClient::new(test_socket).unwrap(); println!("{:?}", client); let version = client.get_version().unwrap(); @@ -1389,7 +1403,7 @@ mod tests { fn test_get_volumes() { // Our test now calls the correct helper function automatically. let test_socket = get_test_socket_path(); - let mut client = DockerClient::new(test_socket); + let mut client = DockerClient::new(test_socket).unwrap(); println!("{:?}", client); let volumes = client.get_volumes().unwrap(); @@ -1398,10 +1412,11 @@ mod tests { } #[test] + /* this test is not good for everyone */ fn test_get_volume_details() { // Our test now calls the correct helper function automatically. let test_socket = get_test_socket_path(); - let mut client = DockerClient::new(test_socket); + let mut client = DockerClient::new(test_socket).unwrap(); println!("{:?}", client); let volume_name = diff --git a/crates/docker/src/requests.rs b/crates/docker/src/requests.rs index 4a6bf04..77e0393 100644 --- a/crates/docker/src/requests.rs +++ b/crates/docker/src/requests.rs @@ -124,7 +124,6 @@ impl TeusRequestBuilder { lines.collect::() } else { println!("--> Detected Content-Length response. Body is raw JSON."); - // If not chunked, the body is already the complete JSON. No processing needed. body_part.to_string() } } @@ -168,9 +167,15 @@ impl TeusRequestBuilder { mod tests { use super::*; + #[cfg(not(target_os = "macos"))] + const _SOCK_SRC: &str = "/var/run/docker.sock"; + + #[cfg(target_os = "macos")] + const _SOCK_SRC: &str = "/Users/homeerr/.colima/default/docker.sock"; + // Helper function to avoid repeating setup code fn _setup_builder() -> TeusRequestBuilder { - let socket = "/Users/homeerr/.colima/default/docker.sock".to_string(); + let socket = _SOCK_SRC.to_string(); let host = "localhost".to_string(); TeusRequestBuilder::new(socket, host).unwrap() } diff --git a/crates/teus-api/Cargo.toml b/crates/teus-api/Cargo.toml new file mode 100644 index 0000000..2a02042 --- /dev/null +++ b/crates/teus-api/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "teus-api" +version = "0.1.0" +edition = "2024" + +[dependencies] +docker = { path = "../docker" } +teus-types = { path = "../teus-types" } +teus-auth = { path = "../teus-auth" } +teus-monitor = { path = "../teus-monitor" } +teus-docker = { path = "../teus-docker" } +teus-database = { path = "../teus-database"} +teus-config = { path = "../teus-config"} +teus-services = { path = "../teus-services" } +actix-web = "4.9" +actix-cors = "0.7" +sysinfo = "0.33.1" diff --git a/teus/webserver/services/mod.rs b/crates/teus-api/src/handlers/mod.rs similarity index 100% rename from teus/webserver/services/mod.rs rename to crates/teus-api/src/handlers/mod.rs diff --git a/teus/webserver/services/systeminfo.rs b/crates/teus-api/src/handlers/systeminfo.rs similarity index 93% rename from teus/webserver/services/systeminfo.rs rename to crates/teus-api/src/handlers/systeminfo.rs index b407cbd..303f165 100644 --- a/teus/webserver/services/systeminfo.rs +++ b/crates/teus-api/src/handlers/systeminfo.rs @@ -1,7 +1,8 @@ -use crate::webserver::models::sysmodels::{GenericSysInfoResponse, IpInfo, MACInfo}; -use actix_web::{get, HttpResponse, Responder}; +use actix_web::{HttpResponse, Responder, get}; use sysinfo::{Networks, System}; +use teus_types::api_models::{GenericSysInfoResponse, IpInfo, MACInfo}; +/* TODO: Migrate those services into teus-services crate */ fn collect_network_info() -> Vec { let networks = Networks::new_with_refreshed_list(); let mut ip_structs = Vec::new(); diff --git a/teus/webserver/docker/mod.rs b/crates/teus-api/src/lib.rs similarity index 52% rename from teus/webserver/docker/mod.rs rename to crates/teus-api/src/lib.rs index c3d4495..c0c696a 100644 --- a/teus/webserver/docker/mod.rs +++ b/crates/teus-api/src/lib.rs @@ -1 +1,2 @@ pub mod handlers; +pub mod routes; diff --git a/teus/webserver/api.rs b/crates/teus-api/src/routes.rs similarity index 81% rename from teus/webserver/api.rs rename to crates/teus-api/src/routes.rs index cb5cd86..46508ab 100644 --- a/teus/webserver/api.rs +++ b/crates/teus-api/src/routes.rs @@ -1,18 +1,28 @@ -use crate::bookmarks::handlers as bookmark_handlers; -use crate::config::handlers::get_teus_config; -use crate::monitor::query; -use crate::webserver::auth::handlers::{check, login, signup, JwtConfig}; -use crate::webserver::auth::middleware::AuthMiddlewareFactory; -use crate::webserver::docker::handlers::{ +/* REMOVE SERVICES FROM THIS CRATE */ +/* THIS CRATE IS ONLY FOR HANDLE THE ACTIX WEBSERVICE */ + +use std::sync::Mutex; + +use crate::handlers::systeminfo; +use actix_cors::Cors; +use actix_web::error::ErrorInternalServerError; +use actix_web::{App, Error, HttpResponse, HttpServer, get, http, middleware, web}; +use docker::docker::DockerClient; +use teus_auth::handlers::{JwtConfig, check, login, signup}; +use teus_auth::middleware::AuthMiddlewareFactory; +use teus_config::config::handlers::get_teus_config; +use teus_database::storage::Storage; +use teus_docker::handlers::{ get_docker_container, get_docker_containers, get_docker_version, get_docker_volume, get_docker_volumes, }; -use crate::webserver::models::sysmodels::{DiskInfoResponse, SysInfoResponse}; -use crate::webserver::services::systeminfo; -use crate::{config::types::Config, monitor::storage::Storage}; -use actix_cors::Cors; -use actix_web::error::ErrorInternalServerError; -use actix_web::{get, http, middleware, web, App, Error, HttpResponse, HttpServer}; +use teus_monitor::query; +use teus_services::bookmarks::handlers as bookmark_handlers; +use teus_types::api_models::{DiskInfoResponse, SysInfoResponse}; +use teus_types::config::Config; + +pub type DockerState = web::Data>>; + // TODO: move this api into another file `syshandler` or something #[get("/sysinfo")] @@ -64,6 +74,9 @@ pub async fn start_webserver(config: &Config, storage: Storage) -> std::io::Resu let app_config_data = web::Data::new(config.clone()); let app_storage_data = web::Data::new(storage.clone()); // Clone for app_data + /* to avoid re-initialize the client at every api request */ + let docker_state = web::Data::new(Mutex::new(None::)); + // TODO: Put the secret here from the config let jwt_secret = config.server.secret.clone(); let jwt_config = web::Data::new(JwtConfig { @@ -85,6 +98,7 @@ pub async fn start_webserver(config: &Config, storage: Storage) -> std::io::Resu .app_data(app_config_data.clone()) // Share config .app_data(app_storage_data.clone()) // Share storage .app_data(jwt_config.clone()) // Share JWT config + .app_data(docker_state.clone()) // Public routes .service( web::scope("/api/v1/auth") diff --git a/crates/teus-auth/Cargo.toml b/crates/teus-auth/Cargo.toml new file mode 100644 index 0000000..90ea1d8 --- /dev/null +++ b/crates/teus-auth/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "teus-auth" +version = "0.1.0" +edition = "2024" + +[dependencies] +teus-types = { path = "../teus-types" } +teus-database = { path = "../teus-database" } +teus-config = { path = "../teus-config" } +teus-schema = { path = "../teus-schema" } +actix-web = "4.9" +jsonwebtoken = "9.3" +argon2 = "0.5" +chrono = { version = "0.4", features = ["serde"] } +serde = { version = "1.0.218", features = ["derive"] } +diesel = { version = "2.2.0", features = [ + "sqlite", + "returning_clauses_for_sqlite_3_35", +] } diff --git a/teus/webserver/auth/handlers.rs b/crates/teus-auth/src/handlers.rs similarity index 97% rename from teus/webserver/auth/handlers.rs rename to crates/teus-auth/src/handlers.rs index f8bb6c3..9ddab25 100644 --- a/teus/webserver/auth/handlers.rs +++ b/crates/teus-auth/src/handlers.rs @@ -1,16 +1,16 @@ -use crate::{ - config::{schema::TeusConfig, types::Config}, - monitor::storage::Storage, - webserver::auth::{middleware::Claims, schema::User}, -}; -use actix_web::{post, web, HttpResponse, Responder}; +use crate::middleware::Claims; +use crate::schema::User; +use actix_web::{HttpResponse, Responder, post, web}; use argon2::{ - password_hash::{PasswordHash, PasswordVerifier}, Argon2, + password_hash::{PasswordHash, PasswordVerifier}, }; use chrono::{Duration, Utc}; -use jsonwebtoken::{encode, EncodingKey, Header}; +use jsonwebtoken::{EncodingKey, Header, encode}; use serde::{Deserialize, Serialize}; +use teus_config::config::schema::TeusConfig; +use teus_database::storage::Storage; +use teus_types::config::Config; /// Request structure for user authentication login endpoint. /// diff --git a/teus/webserver/auth/mod.rs b/crates/teus-auth/src/lib.rs similarity index 100% rename from teus/webserver/auth/mod.rs rename to crates/teus-auth/src/lib.rs diff --git a/teus/webserver/auth/middleware.rs b/crates/teus-auth/src/middleware.rs similarity index 97% rename from teus/webserver/auth/middleware.rs rename to crates/teus-auth/src/middleware.rs index e0e46f0..2c15473 100644 --- a/teus/webserver/auth/middleware.rs +++ b/crates/teus-auth/src/middleware.rs @@ -5,14 +5,14 @@ //! from the Authorization header, making user claims available to handlers. use actix_web::{ - dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform}, - error::ErrorUnauthorized, Error, HttpMessage, + dev::{Service, ServiceRequest, ServiceResponse, Transform, forward_ready}, + error::ErrorUnauthorized, }; -use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation}; +use jsonwebtoken::{Algorithm, DecodingKey, Validation, decode}; use serde::{Deserialize, Serialize}; use std::{ - future::{ready, Future, Ready}, + future::{Future, Ready, ready}, pin::Pin, rc::Rc, }; diff --git a/teus/webserver/auth/mutation.rs b/crates/teus-auth/src/mutation.rs similarity index 96% rename from teus/webserver/auth/mutation.rs rename to crates/teus-auth/src/mutation.rs index 6fe84c3..39e50f0 100644 --- a/teus/webserver/auth/mutation.rs +++ b/crates/teus-auth/src/mutation.rs @@ -1,6 +1,6 @@ use super::schema::User; -use argon2::password_hash::rand_core::OsRng; use argon2::password_hash::SaltString; +use argon2::password_hash::rand_core::OsRng; use argon2::{Argon2, PasswordHasher}; use diesel::result::Error; use diesel::{RunQueryDsl, SqliteConnection}; @@ -11,7 +11,7 @@ impl User { username: &str, password: &str, ) -> Result { - use crate::schema::user; + use teus_schema::schema::user; // Get a random salt for the password let salt = SaltString::generate(&mut OsRng); diff --git a/teus/webserver/auth/query.rs b/crates/teus-auth/src/query.rs similarity index 88% rename from teus/webserver/auth/query.rs rename to crates/teus-auth/src/query.rs index a6ab817..4e17a65 100644 --- a/teus/webserver/auth/query.rs +++ b/crates/teus-auth/src/query.rs @@ -6,7 +6,7 @@ impl User { conn: &mut SqliteConnection, username_q: &str, ) -> Result, Error> { - use crate::schema::user::dsl::*; + use teus_schema::schema::user::dsl::*; user.filter(username.eq(username_q)) .select(User::as_select()) diff --git a/teus/webserver/auth/schema.rs b/crates/teus-auth/src/schema.rs similarity index 98% rename from teus/webserver/auth/schema.rs rename to crates/teus-auth/src/schema.rs index a4676ef..05d4c00 100644 --- a/teus/webserver/auth/schema.rs +++ b/crates/teus-auth/src/schema.rs @@ -6,6 +6,7 @@ use diesel::prelude::*; use serde::Serialize; +use teus_schema::schema; /// Database schema structure for user accounts. /// @@ -46,7 +47,7 @@ use serde::Serialize; /// - `query.rs`: Contains `User::find_by_username()` for authentication /// - `handlers.rs`: Uses this structure in login/signup endpoints #[derive(Insertable, Queryable, Selectable, Serialize, Debug)] -#[diesel(table_name = crate::schema::user)] +#[diesel(table_name = schema::user)] #[diesel(check_for_backend(diesel::sqlite::Sqlite))] pub struct User { /// Database-generated unique identifier for the user. diff --git a/crates/teus-config/Cargo.toml b/crates/teus-config/Cargo.toml new file mode 100644 index 0000000..74cb0e9 --- /dev/null +++ b/crates/teus-config/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "teus-config" +version = "0.1.0" +edition = "2024" + +[dependencies] +teus-types = { path = "../teus-types" } +teus-schema = { path = "../teus-schema" } +teus-database = { path = "../teus-database" } +diesel = { version = "2.2.0", features = ["sqlite", "returning_clauses_for_sqlite_3_35"] } +actix-web = "4.9.0" +serde = { version = "1.0", features = ["derive"] } +toml = "0.8" + +[dev-dependencies] +tempfile = "3.8" diff --git a/teus/config/handlers.rs b/crates/teus-config/src/config/handlers.rs similarity index 91% rename from teus/config/handlers.rs rename to crates/teus-config/src/config/handlers.rs index 29e99d3..46c31b7 100644 --- a/teus/config/handlers.rs +++ b/crates/teus-config/src/config/handlers.rs @@ -1,13 +1,10 @@ -use crate::{ - config::{ - schema, - types::{Config, IsFirstVisitResponse}, - }, - monitor::storage::Storage, -}; +use crate::config::schema; use actix_web::error::ErrorInternalServerError; -use actix_web::{get, web, Error, HttpResponse}; +use actix_web::{Error, HttpResponse, get, web}; +use teus_database::storage::Storage; +use teus_types::config::{Config, IsFirstVisitResponse}; +/* is this really useful? */ #[get("/teus-config")] pub async fn get_teus_config(config: web::Data) -> Result { let storage = Storage::new(&config.database.path).map_err(|e| { diff --git a/teus/config/mod.rs b/crates/teus-config/src/config/mod.rs similarity index 84% rename from teus/config/mod.rs rename to crates/teus-config/src/config/mod.rs index 9054531..428b458 100644 --- a/teus/config/mod.rs +++ b/crates/teus-config/src/config/mod.rs @@ -3,4 +3,3 @@ pub mod mutation; pub mod parser; pub mod query; pub mod schema; -pub mod types; diff --git a/teus/config/mutation.rs b/crates/teus-config/src/config/mutation.rs similarity index 91% rename from teus/config/mutation.rs rename to crates/teus-config/src/config/mutation.rs index e352e9f..0c52edf 100644 --- a/teus/config/mutation.rs +++ b/crates/teus-config/src/config/mutation.rs @@ -5,7 +5,8 @@ use diesel::{RunQueryDsl, SqliteConnection}; impl TeusConfig { pub fn set_first_visit(conn: &mut SqliteConnection, is_first_visit: bool) -> Result<(), Error> { - use crate::schema::config::dsl::*; + use teus_schema::schema::config::dsl::*; + // use crate::schema::config::dsl::*; // Get the first config record let teus_config = config diff --git a/teus/config/parser.rs b/crates/teus-config/src/config/parser.rs similarity index 98% rename from teus/config/parser.rs rename to crates/teus-config/src/config/parser.rs index a299892..4e1b46b 100644 --- a/teus/config/parser.rs +++ b/crates/teus-config/src/config/parser.rs @@ -1,6 +1,6 @@ -use crate::config::types::Config; use std::error::Error; use std::{fs, path::Path}; +use teus_types::config::Config; #[allow(dead_code)] type GeneralError = Box; diff --git a/teus/config/query.rs b/crates/teus-config/src/config/query.rs similarity index 83% rename from teus/config/query.rs rename to crates/teus-config/src/config/query.rs index 836b05b..f434b45 100644 --- a/teus/config/query.rs +++ b/crates/teus-config/src/config/query.rs @@ -4,7 +4,8 @@ use diesel::result::Error; impl TeusConfig { pub fn is_first_visit(conn: &mut SqliteConnection) -> Result { - use crate::schema::config::dsl::*; + // use crate::schema::config::dsl::*; + use teus_schema::schema::config::dsl::*; config.select(first_visit).first(conn) } @@ -12,7 +13,7 @@ impl TeusConfig { pub fn get_teus_server_config( conn: &mut SqliteConnection, ) -> Result, Error> { - use crate::schema::config::dsl::*; + use teus_schema::schema::config::dsl::*; let latest_teusconfig_option = config .select(TeusConfig::as_select()) diff --git a/teus/config/schema.rs b/crates/teus-config/src/config/schema.rs similarity index 82% rename from teus/config/schema.rs rename to crates/teus-config/src/config/schema.rs index f84ed61..693f64c 100644 --- a/teus/config/schema.rs +++ b/crates/teus-config/src/config/schema.rs @@ -1,9 +1,10 @@ use diesel::prelude::*; use serde::{Deserialize, Serialize}; +use teus_schema::schema; // You might also want structs for querying data later #[derive(Queryable, Selectable, Debug, Serialize, Deserialize)] -#[diesel(table_name = crate::schema::config)] +#[diesel(table_name = schema::config)] #[diesel(check_for_backend(diesel::sqlite::Sqlite))] pub struct TeusConfig { pub id: Option, diff --git a/crates/teus-config/src/lib.rs b/crates/teus-config/src/lib.rs new file mode 100644 index 0000000..ef68c36 --- /dev/null +++ b/crates/teus-config/src/lib.rs @@ -0,0 +1 @@ +pub mod config; diff --git a/crates/teus-database/Cargo.toml b/crates/teus-database/Cargo.toml new file mode 100644 index 0000000..056a08a --- /dev/null +++ b/crates/teus-database/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "teus-database" +version = "0.1.0" +edition = "2024" + +[dependencies] +teus-types = { path = "../teus-types" } +diesel = { version = "2.2.0", features = ["sqlite", "returning_clauses_for_sqlite_3_35"] } + +[dev-dependencies] +tempfile = "3.8" diff --git a/crates/teus-database/src/lib.rs b/crates/teus-database/src/lib.rs new file mode 100644 index 0000000..30f61eb --- /dev/null +++ b/crates/teus-database/src/lib.rs @@ -0,0 +1 @@ +pub mod storage; diff --git a/teus/monitor/storage.rs b/crates/teus-database/src/storage.rs similarity index 98% rename from teus/monitor/storage.rs rename to crates/teus-database/src/storage.rs index 8c913c0..d0f5213 100644 --- a/teus/monitor/storage.rs +++ b/crates/teus-database/src/storage.rs @@ -4,8 +4,8 @@ use std::error::Error; use std::path::Path; use std::sync::{Arc, Mutex}; // Added for Box -// Removed: use rusqlite::{Connection, Result}; -// Removed: use std::time::Duration; +/* to avoid to add diesel dep on crates */ +pub type TeuSQLiteConnection = SqliteConnection; #[derive(Clone)] pub struct Storage { diff --git a/crates/teus-docker/Cargo.toml b/crates/teus-docker/Cargo.toml new file mode 100644 index 0000000..7a4400e --- /dev/null +++ b/crates/teus-docker/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "teus-docker" +version = "0.1.0" +edition = "2024" + +[dependencies] +teus-types = { path = "../teus-types" } +docker = { path = "../docker" } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +tokio = { version = "1", features = ["full"] } +actix-web = "4.9" +serde_qs = "0.13" diff --git a/crates/teus-docker/src/errors.rs b/crates/teus-docker/src/errors.rs new file mode 100644 index 0000000..759749a --- /dev/null +++ b/crates/teus-docker/src/errors.rs @@ -0,0 +1,31 @@ +use std::fmt::Display; + +use actix_web::ResponseError; +use docker::docker::DockerError; + +#[derive(Debug)] +pub enum ApiError { + Docker(DockerError), + Serialization(serde_qs::Error), + ServiceUnavailable(String), +} + +impl Display for ApiError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ApiError::Docker(e) => write!(f, "An error occurred with the Docker API: {:?}", e), + ApiError::Serialization(e) => write!(f, "Failed to serialize query parameters: {}", e), + ApiError::ServiceUnavailable(msg) => write!(f, "{}", msg), + } + } +} + +impl ResponseError for ApiError { + fn status_code(&self) -> actix_web::http::StatusCode { + match self { + ApiError::Docker(_) => actix_web::http::StatusCode::INTERNAL_SERVER_ERROR, + ApiError::Serialization(_) => actix_web::http::StatusCode::BAD_REQUEST, + ApiError::ServiceUnavailable(_) => actix_web::http::StatusCode::SERVICE_UNAVAILABLE, + } + } +} diff --git a/crates/teus-docker/src/handlers.rs b/crates/teus-docker/src/handlers.rs new file mode 100644 index 0000000..a73c1a4 --- /dev/null +++ b/crates/teus-docker/src/handlers.rs @@ -0,0 +1,101 @@ +use crate::errors::ApiError; +use actix_web::{HttpResponse, get, web}; +use docker::docker::{DockerClient, DockerError}; +use serde::{Deserialize, Serialize}; +use serde_qs::to_string; +use std::{fmt::Debug, sync::Mutex}; + +/* alias to get the life easier */ +type DockerState = web::Data>>; + +/* get the docker client from the state */ +fn get_client(state: &DockerState) -> Result { + let mut guard = state.lock().unwrap(); // lock the mutex + + if let Some(client) = guard.as_ref() { + return Ok(client.clone()); + } + + match DockerClient::new(None) { + Ok(client) => { + *guard = Some(client.clone()); + Ok(client) + } + Err(_) => Err(DockerError::Generic( + "Could not connect to the Docker socket. Is Docker running?".to_string(), + )), + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct GenericDockerResponse { + message: String, +} + +#[derive(Debug, Deserialize, Serialize)] +struct ContainersQuery { + all: Option, +} + +#[get("/docker/version")] +async fn get_docker_version(docker_state: DockerState) -> Result { + let mut docker_client = get_client(&docker_state).map_err(|e| ApiError::Docker(e))?; + + match docker_client.get_version() { + Ok(version) => Ok(HttpResponse::Ok().json(version)), + Err(err) => Err(ApiError::Docker(err)), + } +} + +#[get("/docker/containers")] +async fn get_docker_containers( + query: web::Query, + docker_state: DockerState, +) -> Result { + let query_params: ContainersQuery = query.into_inner(); + let query_string = to_string(&query_params).unwrap(); + let mut docker_client = get_client(&docker_state).map_err(|e| ApiError::Docker(e))?; + + match docker_client.get_containers(Some(query_string)) { + Ok(containers) => Ok(HttpResponse::Ok().json(containers)), + Err(err) => Err(ApiError::Docker(err)), + } +} + +#[get("/docker/container/{id}")] +async fn get_docker_container( + id: web::Path, + docker_state: DockerState, +) -> Result { + let mut docker_client = get_client(&docker_state).map_err(|e| ApiError::Docker(e))?; + let container_id_clone = id.clone(); + + match docker_client.get_container_details(container_id_clone) { + Ok(container) => Ok(HttpResponse::Ok().json(container)), + Err(err) => Err(ApiError::Docker(err)), + } +} + +#[get("/docker/volumes")] +async fn get_docker_volumes(docker_state: DockerState) -> Result { + let mut docker_client = get_client(&docker_state).map_err(|e| ApiError::Docker(e))?; + + match docker_client.get_volumes() { + Ok(volumes) => Ok(HttpResponse::Ok().json(volumes)), + Err(err) => Err(ApiError::Docker(err)), + } +} + +#[get("/docker/volumes/{id}")] +async fn get_docker_volume( + id: web::Path, + docker_state: DockerState, +) -> Result { + let mut docker_client = get_client(&docker_state).map_err(|e| ApiError::Docker(e))?; + + let cloned_id = id.clone(); + match docker_client.get_volume_details(cloned_id) { + Ok(volume) => Ok(HttpResponse::Ok().json(volume)), + Err(err) => Err(ApiError::Docker(err)), + } +} diff --git a/crates/teus-docker/src/lib.rs b/crates/teus-docker/src/lib.rs new file mode 100644 index 0000000..0e2fecc --- /dev/null +++ b/crates/teus-docker/src/lib.rs @@ -0,0 +1,2 @@ +pub mod errors; +pub mod handlers; \ No newline at end of file diff --git a/crates/teus-monitor/Cargo.toml b/crates/teus-monitor/Cargo.toml new file mode 100644 index 0000000..04e113a --- /dev/null +++ b/crates/teus-monitor/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "teus-monitor" +version = "0.1.0" +edition = "2024" + +[dependencies] +teus-types = { path = "../teus-types" } +teus-database = { path = "../teus-database" } +teus-schema = { path = "../teus-schema"} +sysinfo = "0.33" +chrono = { version = "0.4", features = ["serde"] } +diesel = { version = "2.2.0", features = [ + "sqlite", + "returning_clauses_for_sqlite_3_35", +] } +serde = { version = "1.0.218", features = ["derive"] } + +[dev-dependencies] +serde_json = "1.0" diff --git a/teus/monitor/mod.rs b/crates/teus-monitor/src/lib.rs similarity index 78% rename from teus/monitor/mod.rs rename to crates/teus-monitor/src/lib.rs index cc1208a..9b0c93b 100644 --- a/teus/monitor/mod.rs +++ b/crates/teus-monitor/src/lib.rs @@ -1,5 +1,4 @@ pub mod mutation; pub mod query; pub mod schema; -pub mod storage; pub mod sys; diff --git a/teus/monitor/mutation.rs b/crates/teus-monitor/src/mutation.rs similarity index 88% rename from teus/monitor/mutation.rs rename to crates/teus-monitor/src/mutation.rs index 942e74c..2f4bb5f 100644 --- a/teus/monitor/mutation.rs +++ b/crates/teus-monitor/src/mutation.rs @@ -1,5 +1,5 @@ // src/monitor/mutation.rs -use crate::monitor::schema::{SchemaDiskInfo, SchemaSysInfo}; +use crate::schema::{SchemaDiskInfo, SchemaSysInfo}; use diesel::prelude::*; use diesel::result::Error; @@ -8,7 +8,7 @@ pub fn insert_sysinfo( conn: &mut SqliteConnection, new_sys_info: &SchemaSysInfo, ) -> Result { - use crate::schema::sysinfo::dsl::*; + use teus_schema::schema::sysinfo::dsl::*; diesel::insert_into(sysinfo) .values(new_sys_info) @@ -33,7 +33,7 @@ pub fn insert_diskinfo( conn: &mut SqliteConnection, new_disk_info: &SchemaDiskInfo, ) -> Result { - use crate::schema::diskinfo::dsl::*; + use teus_schema::schema::diskinfo::dsl::*; diesel::insert_into(diskinfo) .values(new_disk_info) @@ -45,7 +45,7 @@ pub fn insert_multiple_diskinfo( conn: &mut SqliteConnection, disk_infos: &[SchemaDiskInfo], ) -> Result { - use crate::schema::diskinfo::dsl::*; + use teus_schema::schema::diskinfo::dsl::*; diesel::insert_into(diskinfo) .values(disk_infos) diff --git a/teus/monitor/query.rs b/crates/teus-monitor/src/query.rs similarity index 77% rename from teus/monitor/query.rs rename to crates/teus-monitor/src/query.rs index 2bd32e4..848a6dd 100644 --- a/teus/monitor/query.rs +++ b/crates/teus-monitor/src/query.rs @@ -1,4 +1,4 @@ -use crate::monitor::schema::{DiskInfo, SysInfo}; +use crate::schema::{DiskInfo, SysInfo}; use diesel::prelude::*; use diesel::result::Error; @@ -6,9 +6,8 @@ use diesel::result::Error; pub fn get_latest_sysinfo_with_disks( conn: &mut SqliteConnection, ) -> Result)>, Error> { - use crate::schema::sysinfo::dsl::*; + use teus_schema::schema::sysinfo::dsl::*; - // 1. Get the latest SysInfo record let latest_sysinfo_option = sysinfo .order(id.desc()) // Order by ID descending to get the latest .select(SysInfo::as_select()) @@ -17,8 +16,8 @@ pub fn get_latest_sysinfo_with_disks( match latest_sysinfo_option { Some(latest_sysinfo) => { - // 2. If a SysInfo record was found, find all DiskInfo records that match - use crate::schema::diskinfo::dsl::*; + /* import here because the ID is ambiguos */ + use teus_schema::schema::diskinfo::dsl::*; let disks = diskinfo .filter(sysinfo_id.eq(latest_sysinfo.id.unwrap())) diff --git a/teus/monitor/schema.rs b/crates/teus-monitor/src/schema.rs similarity index 99% rename from teus/monitor/schema.rs rename to crates/teus-monitor/src/schema.rs index 257aa65..e64d7e1 100644 --- a/teus/monitor/schema.rs +++ b/crates/teus-monitor/src/schema.rs @@ -5,9 +5,9 @@ //! both insertable structures for writing new data and queryable //! structures for reading existing data. -use crate::schema::{diskinfo, sysinfo}; use diesel::prelude::*; use serde::{Deserialize, Serialize}; +use teus_schema::schema::{diskinfo, sysinfo}; /// Structure for inserting system information records into the database. /// diff --git a/teus/monitor/sys.rs b/crates/teus-monitor/src/sys.rs similarity index 97% rename from teus/monitor/sys.rs rename to crates/teus-monitor/src/sys.rs index 594ed69..475990a 100644 --- a/teus/monitor/sys.rs +++ b/crates/teus-monitor/src/sys.rs @@ -1,8 +1,10 @@ use super::mutation; use super::schema::{SchemaDiskInfo, SchemaSysInfo}; // Import the Diesel insertable structs -use crate::{config::types::Config, monitor::storage::Storage}; use chrono::Utc; -use diesel::SqliteConnection; // Import SqliteConnection +use teus_database::storage::Storage; +use teus_database::storage::TeuSQLiteConnection; +use teus_types::config::Config; +// use diesel::SqliteConnection; // Import SqliteConnection use std::{thread, time::Duration}; // Import Mutex use sysinfo::{Disks, MemoryRefreshKind, System}; @@ -94,7 +96,7 @@ impl SysInfo { } }; // Dereference the guard to get the &mut SqliteConnection - let conn: &mut SqliteConnection = &mut *conn_guard; + let conn: &mut TeuSQLiteConnection = &mut *conn_guard; let mut sys = System::new_all(); let disks_sysinfo = Disks::new_with_refreshed_list(); // Renamed to avoid conflict @@ -118,7 +120,6 @@ impl SysInfo { 0.0 }; - // --- Prepare data for Diesel insertion --- self.timestamp = Utc::now().to_rfc3339(); // Ensure timestamp is current // Create the SchemaSysInfo struct for insertion @@ -180,7 +181,7 @@ impl SysInfo { #[cfg(test)] mod tests { use super::*; - use crate::config::types::{Config, DatabaseConfig, Environment, MonitorConfig, ServerConfig}; + use teus_types::config::{Config, DatabaseConfig, Environment, MonitorConfig, ServerConfig}; #[allow(dead_code)] fn create_test_config() -> Config { diff --git a/crates/teus-schema/Cargo.toml b/crates/teus-schema/Cargo.toml new file mode 100644 index 0000000..ae39f30 --- /dev/null +++ b/crates/teus-schema/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "teus-schema" +version = "0.1.0" +edition = "2024" + +[dependencies] +diesel = { version = "2.2.0", features = ["sqlite", "returning_clauses_for_sqlite_3_35"] } diff --git a/crates/teus-schema/src/lib.rs b/crates/teus-schema/src/lib.rs new file mode 100644 index 0000000..1ce7e17 --- /dev/null +++ b/crates/teus-schema/src/lib.rs @@ -0,0 +1 @@ +pub mod schema; diff --git a/teus/schema.rs b/crates/teus-schema/src/schema.rs similarity index 100% rename from teus/schema.rs rename to crates/teus-schema/src/schema.rs diff --git a/crates/teus-services/Cargo.toml b/crates/teus-services/Cargo.toml new file mode 100644 index 0000000..151d328 --- /dev/null +++ b/crates/teus-services/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "teus-services" +version = "0.1.0" +edition = "2024" + +[dependencies] +teus-monitor = { path = "../teus-monitor" } +teus-types = { path = "../teus-types" } +teus-auth = { path = "../teus-auth" } +teus-database = { path = "../teus-database" } +teus-schema = { path = "../teus-schema" } +serde_json = "1.0" +actix-web = "4.9.0" +serde = { version = "1.0.218", features = ["derive"] } +diesel = { version = "2.2.0", features = [ + "sqlite", + "returning_clauses_for_sqlite_3_35", +] } diff --git a/teus/bookmarks/handlers.rs b/crates/teus-services/src/bookmarks/handlers.rs similarity index 95% rename from teus/bookmarks/handlers.rs rename to crates/teus-services/src/bookmarks/handlers.rs index 91e27a6..7562787 100644 --- a/teus/bookmarks/handlers.rs +++ b/crates/teus-services/src/bookmarks/handlers.rs @@ -1,8 +1,8 @@ use crate::bookmarks::schema::{NewService, Service, ServicePatchPayload, ServicePayload}; -use crate::config::types::Config; -use crate::monitor::storage::Storage; -use crate::webserver::auth::middleware::Claims; -use actix_web::{delete, get, patch, post, web, HttpMessage, HttpRequest, HttpResponse, Responder}; +use actix_web::{HttpMessage, HttpRequest, HttpResponse, Responder, delete, get, patch, post, web}; +use teus_auth::middleware::Claims; +use teus_database::storage::Storage; +use teus_types::config::Config; #[allow(dead_code)] /// Helper function to extract claims from request @@ -63,7 +63,7 @@ pub async fn add_service( Err(_) => { return HttpResponse::InternalServerError().json(serde_json::json!({ "message": "Error creating a new Service", - })) + })); } }; diff --git a/teus/bookmarks/mod.rs b/crates/teus-services/src/bookmarks/mod.rs similarity index 100% rename from teus/bookmarks/mod.rs rename to crates/teus-services/src/bookmarks/mod.rs diff --git a/teus/bookmarks/mutation.rs b/crates/teus-services/src/bookmarks/mutation.rs similarity index 91% rename from teus/bookmarks/mutation.rs rename to crates/teus-services/src/bookmarks/mutation.rs index 164e52b..1a1cd28 100644 --- a/teus/bookmarks/mutation.rs +++ b/crates/teus-services/src/bookmarks/mutation.rs @@ -9,7 +9,7 @@ impl Service { conn: &mut SqliteConnection, new_service: NewService, ) -> Result { - use crate::schema::services; + use teus_schema::schema::services; diesel::insert_into(services::table) .values(&new_service) @@ -22,7 +22,7 @@ impl Service { conn: &mut SqliteConnection, user_id_claim: i32, ) -> Result, Error> { - use crate::schema::services::dsl::*; + use teus_schema::schema::services::dsl::*; services .filter(user_id.eq(user_id_claim)) @@ -35,7 +35,7 @@ impl Service { conn: &mut SqliteConnection, service_id: i32, ) -> Result { - use crate::schema::services::dsl::*; + use teus_schema::schema::services::dsl::*; services .filter(id.eq(service_id)) @@ -50,7 +50,7 @@ impl Service { user_query_id: i32, updated_service: NewService, ) -> Result { - use crate::schema::services::dsl::*; + use teus_schema::schema::services::dsl::*; diesel::update(services.filter(id.eq(service_id).and(user_id.eq(user_query_id)))) .set(( @@ -87,7 +87,7 @@ impl Service { service_id: i32, user_query_id: i32, ) -> Result { - use crate::schema::services::dsl::*; + use teus_schema::schema::services::dsl::*; diesel::delete(services.filter(id.eq(service_id).and(user_id.eq(user_query_id)))) .execute(conn) diff --git a/teus/bookmarks/schema.rs b/crates/teus-services/src/bookmarks/schema.rs similarity index 91% rename from teus/bookmarks/schema.rs rename to crates/teus-services/src/bookmarks/schema.rs index ace354b..f4f96eb 100644 --- a/teus/bookmarks/schema.rs +++ b/crates/teus-services/src/bookmarks/schema.rs @@ -1,12 +1,15 @@ use diesel::prelude::*; use serde::{Deserialize, Serialize}; +/* schemas */ +use teus_schema::schema; + #[allow(dead_code)] pub type Bookmarks = Vec; // For querying existing services from the database #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Queryable, Selectable)] -#[diesel(table_name = crate::schema::services)] +#[diesel(table_name = schema::services)] #[diesel(check_for_backend(diesel::sqlite::Sqlite))] #[serde(rename_all = "camelCase")] pub struct Service { @@ -19,7 +22,7 @@ pub struct Service { // For inserting new services into the database #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Insertable)] -#[diesel(table_name = crate::schema::services)] +#[diesel(table_name = schema::services)] #[diesel(check_for_backend(diesel::sqlite::Sqlite))] #[serde(rename_all = "camelCase")] pub struct NewService { diff --git a/crates/teus-services/src/lib.rs b/crates/teus-services/src/lib.rs new file mode 100644 index 0000000..bf3e888 --- /dev/null +++ b/crates/teus-services/src/lib.rs @@ -0,0 +1 @@ +pub mod bookmarks; diff --git a/crates/teus-types/Cargo.toml b/crates/teus-types/Cargo.toml new file mode 100644 index 0000000..ff12731 --- /dev/null +++ b/crates/teus-types/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "teus-types" +version = "0.1.0" +edition = "2024" + +[dependencies] +serde = { version = "1.0", features = ["derive"] } +chrono = { version = "0.4", features = ["serde"] } + +[dev-dependencies] +tempfile = "3.8" +toml = "0.8.20" +serde_json = "1.0" diff --git a/teus/webserver/models/sysmodels.rs b/crates/teus-types/src/api_models.rs similarity index 100% rename from teus/webserver/models/sysmodels.rs rename to crates/teus-types/src/api_models.rs diff --git a/teus/config/types.rs b/crates/teus-types/src/config.rs similarity index 100% rename from teus/config/types.rs rename to crates/teus-types/src/config.rs diff --git a/crates/teus-types/src/lib.rs b/crates/teus-types/src/lib.rs new file mode 100644 index 0000000..1d51076 --- /dev/null +++ b/crates/teus-types/src/lib.rs @@ -0,0 +1,2 @@ +pub mod api_models; +pub mod config; diff --git a/install.sh b/install.sh index 9fa9689..dc92c12 100755 --- a/install.sh +++ b/install.sh @@ -78,7 +78,20 @@ echo -e "========================================${NC}" # Check for sudo privileges if [[ $EUID -ne 0 && "$(id -u)" -ne 0 ]]; then if ! command -v sudo >/dev/null 2>&1; then - error "This script requires sudo privileges. Please run as root or install sudo." + error "This script requires sudo privileges." + fi +fi + +# Check if the user teus is inside docker group +if ! id -nG teus | grep -qw "docker"; then + warning "The user 'teus' is not in the 'docker' group. Please add the user to the docker group and try again." + read -rp "Do you want to add the user 'teus' to the docker group? [Y/n] " add_to_docker_group + add_to_docker_group=${add_to_docker_group:-Y} + if [[ $add_to_docker_group =~ ^[Yy]$ ]]; then + sudo usermod -aG docker teus + success "User 'teus' added to docker group." + else + error "User 'teus' is not in the docker group. Please add the user to the docker group and try again." fi fi @@ -173,6 +186,10 @@ if ! command -v diesel >/dev/null 2>&1; then if cargo install diesel_cli --no-default-features --features sqlite; then success "Diesel CLI installed successfully." else + # fallback installer to ensure diesel installation + if curl --proto '=https' --tlsv1.2 -LsSf https://github.com/diesel-rs/diesel/releases/latest/download/diesel_cli-installer.sh | sh; then + success "Diesel CLI installed successfully. " + fi error "Failed to install Diesel CLI. Please install it manually with: cargo install diesel_cli --no-default-features --features sqlite" fi else @@ -327,4 +344,4 @@ if [[ $install_dashboard =~ ^[Yy]$ ]]; then info "Setting up web dashboard..." success "Web dashboard installed successfully." info "You can access the web dashboard at: http://localhost:8080" -fi \ No newline at end of file +fi diff --git a/migrations/2025-04-15-220022_create_config/up.sql b/migrations/2025-04-15-220022_create_config/up.sql index ee00d0d..c7f475c 100644 --- a/migrations/2025-04-15-220022_create_config/up.sql +++ b/migrations/2025-04-15-220022_create_config/up.sql @@ -5,4 +5,4 @@ CREATE TABLE config ( first_visit BOOLEAN NOT NULL DEFAULT 1 ); -INSERT INTO config (first_visit) VALUES (0); +INSERT INTO config (first_visit) VALUES (1); diff --git a/teus/lib.rs b/teus/lib.rs index 14fdc1a..b5614dd 100644 --- a/teus/lib.rs +++ b/teus/lib.rs @@ -1,6 +1 @@ -pub mod bookmarks; -pub mod config; -pub mod monitor; -pub mod schema; pub mod utils; -pub mod webserver; diff --git a/teus/main.rs b/teus/main.rs index 7275b0a..78a15a0 100644 --- a/teus/main.rs +++ b/teus/main.rs @@ -1,6 +1,3 @@ -use teus::{config, monitor, webserver}; - -use monitor::sys::SysInfo; use std::{ env, path::Path, @@ -11,6 +8,10 @@ use std::{ }, thread, }; +use teus_api::routes; +use teus_config::config; +use teus_database::storage; +use teus_monitor::sys::SysInfo; fn main() { println!("Starting Teus service..."); @@ -37,7 +38,7 @@ fn main() { }; // Initialize Storage once - let storage = match monitor::storage::Storage::new(&config.database.path) { + let storage = match storage::Storage::new(&config.database.path) { Ok(s) => s, Err(e) => { eprintln!("Failed to initialize storage: {}", e); @@ -59,8 +60,8 @@ fn main() { let config_clone_for_web = config.clone(); // Clone config for webserver let storage_clone_for_web = storage.clone(); // Clone storage for webserver let web_handle_thread = thread::spawn(move || { - // This will run the webserver in a separate thread - let _ = webserver::api::start_webserver(&config_clone_for_web, storage_clone_for_web); + /* TODO: consider a RC instead to avoid cloning */ + let _ = routes::start_webserver(&config_clone_for_web, storage_clone_for_web); }); // Give the webserver a moment to start diff --git a/teus/webserver/docker/handlers.rs b/teus/webserver/docker/handlers.rs deleted file mode 100644 index 0e802e8..0000000 --- a/teus/webserver/docker/handlers.rs +++ /dev/null @@ -1,84 +0,0 @@ -use std::fmt::Debug; - -use actix_web::{get, web, HttpResponse, Responder}; -use docker::docker::DockerClient; -use serde::{Deserialize, Serialize}; -use serde_qs::to_string; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct GenericDockerResponse { - message: String, -} - -#[derive(Debug, Deserialize, Serialize)] -struct ContainersQuery { - all: Option, -} - -#[get("/docker/version")] -async fn get_docker_version() -> impl Responder { - let mut docker_client = DockerClient::new(None); - match docker_client.get_version() { - Ok(version) => HttpResponse::Ok().json(version), - Err(err) => HttpResponse::InternalServerError().json(GenericDockerResponse { - message: format!("Error getting docker version: {:?}", err), - }), - } -} - -#[get("/docker/containers")] -async fn get_docker_containers(query: web::Query) -> impl Responder { - println!("Query: {:?}", query); - - let query_params: ContainersQuery = query.into_inner(); - let query_string = to_string(&query_params).unwrap(); - - println!("Query: {:?}", query_string); - let mut docker_client = DockerClient::new(None); - - match docker_client.get_containers(Some(query_string)) { - Ok(containers) => HttpResponse::Ok().json(containers), - Err(err) => HttpResponse::InternalServerError().json(GenericDockerResponse { - message: format!("Error getting docker containers: {:?}", err), - }), - } -} - -#[get("/docker/container/{id}")] -async fn get_docker_container(id: web::Path) -> impl Responder { - let mut docker_client = DockerClient::new(None); - let container_id_clone = id.clone(); - - match docker_client.get_container_details(container_id_clone) { - Ok(container) => HttpResponse::Ok().json(container), - Err(err) => HttpResponse::InternalServerError().json(GenericDockerResponse { - message: format!("Error getting docker container {}: {:?}", id, err), - }), - } -} - -#[get("/docker/volumes")] -async fn get_docker_volumes() -> impl Responder { - let mut docker_client = DockerClient::new(None); - match docker_client.get_volumes() { - Ok(volumes) => HttpResponse::Ok().json(volumes), - Err(err) => HttpResponse::InternalServerError().json(GenericDockerResponse { - message: format!("Error getting docker volumes: {:?}", err), - }), - } -} - -// FIXME: The id is not being passed correctly -// I think the problem is in the enum DockerApi -#[get("/docker/volumes/{id}")] -async fn get_docker_volume(id: web::Path) -> impl Responder { - let mut docker_client = DockerClient::new(None); - - let cloned_id = id.clone(); - match docker_client.get_volume_details(cloned_id) { - Ok(volume) => HttpResponse::Ok().json(volume), - Err(err) => HttpResponse::InternalServerError().json(GenericDockerResponse { - message: format!("Error getting docker volume {} details: {:?}", id, err), - }), - } -} diff --git a/teus/webserver/mod.rs b/teus/webserver/mod.rs deleted file mode 100644 index 5e491be..0000000 --- a/teus/webserver/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod api; -pub mod auth; -pub mod docker; -pub mod models; -pub mod services; diff --git a/teus/webserver/models/mod.rs b/teus/webserver/models/mod.rs deleted file mode 100644 index edad941..0000000 --- a/teus/webserver/models/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod sysmodels;