From 32b584d7d9af4181ec6235963f92204bf9d91eeb Mon Sep 17 00:00:00 2001 From: snow flurry Date: Fri, 23 Sep 2022 22:39:17 -0700 Subject: [PATCH] Initial commit --- .gitignore | 3 + Cargo.lock | 3129 +++++++++++++++++ Cargo.toml | 20 + README.md | 52 + migration/Cargo.toml | 19 + migration/README.md | 41 + migration/src/lib.rs | 12 + .../m20220919_122233_create_instance_data.rs | 69 + migration/src/main.rs | 6 + minccino.toml.example | 16 + src/db.rs | 27 + src/entity/defaults.rs | 23 + src/entity/instance_info.rs | 26 + src/entity/mod.rs | 2 + src/llv6.rs | 49 + src/macros.rs | 21 + src/main.rs | 78 + src/meta/mod.rs | 23 + src/meta/routes.rs | 60 + src/meta/test.rs | 186 + src/test.rs | 25 + src/types.rs | 84 + src/yui/auth.rs | 103 + src/yui/mod.rs | 49 + src/yui/routes.rs | 207 ++ src/yui/test.rs | 145 + 26 files changed, 4475 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 migration/Cargo.toml create mode 100644 migration/README.md create mode 100644 migration/src/lib.rs create mode 100644 migration/src/m20220919_122233_create_instance_data.rs create mode 100644 migration/src/main.rs create mode 100644 minccino.toml.example create mode 100644 src/db.rs create mode 100644 src/entity/defaults.rs create mode 100644 src/entity/instance_info.rs create mode 100644 src/entity/mod.rs create mode 100644 src/llv6.rs create mode 100644 src/macros.rs create mode 100644 src/main.rs create mode 100644 src/meta/mod.rs create mode 100644 src/meta/routes.rs create mode 100644 src/meta/test.rs create mode 100644 src/test.rs create mode 100644 src/types.rs create mode 100644 src/yui/auth.rs create mode 100644 src/yui/mod.rs create mode 100644 src/yui/routes.rs create mode 100644 src/yui/test.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..49e1563 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +db.sql +minccino.toml \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..fd1c6e1 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,3129 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" + +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "opaque-debug", +] + +[[package]] +name = "aes-gcm" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +dependencies = [ + "memchr", +] + +[[package]] +name = "aliasable" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + +[[package]] +name = "async-attributes" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "async-channel" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "once_cell", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0da5b41ee986eed3f524c380e6d64965aea573882a8907682ad100f7859305ca" +dependencies = [ + "async-channel", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", + "tokio", +] + +[[package]] +name = "async-io" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e21f3a490c72b3b0cf44962180e60045de2925d8dff97918f7ee43c8f637c7" +dependencies = [ + "autocfg", + "concurrent-queue", + "futures-lite", + "libc", + "log", + "once_cell", + "parking", + "polling", + "slab", + "socket2", + "waker-fn", + "winapi", +] + +[[package]] +name = "async-lock" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-attributes", + "async-channel", + "async-global-executor", + "async-io", + "async-lock", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-task" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" + +[[package]] +name = "async-trait" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atoi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616896e05fc0e2649463a93a15183c6a16bf03413a7af88ef1285ddedfa9cda5" +dependencies = [ + "num-traits", +] + +[[package]] +name = "atoi" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" +dependencies = [ + "num-traits", +] + +[[package]] +name = "atomic" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b88d82667eca772c4aa12f0f1348b3ae643424c8876448f3f7bd5787032e234c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "atomic-waker" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bae" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b8de67cc41132507eeece2584804efcb15f85ba516e34c944b7667f480397a" +dependencies = [ + "heck 0.3.3", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "binascii" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blocking" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" +dependencies = [ + "async-channel", + "async-task", + "atomic-waker", + "fastrand", + "futures-lite", + "once_cell", +] + +[[package]] +name = "bumpalo" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" + +[[package]] +name = "cache-padded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" +dependencies = [ + "iana-time-zone", + "num-integer", + "num-traits", + "serde", + "winapi", +] + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + +[[package]] +name = "clap" +version = "3.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "once_cell", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" +dependencies = [ + "heck 0.4.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "concurrent-queue" +version = "1.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" +dependencies = [ + "cache-padded", +] + +[[package]] +name = "cookie" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" +dependencies = [ + "aes-gcm", + "base64", + "hkdf", + "hmac", + "percent-encoding", + "rand", + "sha2", + "subtle", + "time", + "version_check", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53757d12b596c16c78b83458d732a5d1a17ab3f53f2f7412f6fb57cc8a140ab3" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff" + +[[package]] +name = "crossbeam-queue" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctor" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdffe87e1d521a10f9696f833fe502293ea446d7f256c06128293a4119bdf4cb" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "ctr" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher", +] + +[[package]] +name = "devise" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c7580b072f1c8476148f16e0a0d5dedddab787da98d86c5082c5e9ed8ab595" +dependencies = [ + "devise_codegen", + "devise_core", +] + +[[package]] +name = "devise_codegen" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123c73e7a6e51b05c75fe1a1b2f4e241399ea5740ed810b0e3e6cacd9db5e7b2" +dependencies = [ + "devise_core", + "quote", +] + +[[package]] +name = "devise_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841ef46f4787d9097405cac4e70fb8644fc037b526e8c14054247c0263c400d0" +dependencies = [ + "bitflags", + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn", +] + +[[package]] +name = "digest" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "dotenvy" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3db6fcad7c1fc4abdd99bf5276a4db30d6a819127903a709ed41e5ff016e84" +dependencies = [ + "dirs", +] + +[[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + +[[package]] +name = "encoding_rs" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + +[[package]] +name = "figment" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e3bd154d9ae2f1bb0ada5b7eebd56529513efa5de7d2fc8c6adf33bc43260cf" +dependencies = [ + "atomic", + "pear", + "serde", + "toml", + "uncased", + "version_check", +] + +[[package]] +name = "flume" +version = "0.10.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" +dependencies = [ + "futures-core", + "futures-sink", + "pin-project", + "spin 0.9.4", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" + +[[package]] +name = "futures-executor" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62007592ac46aa7c2b6416f7deb9a8a8f63a01e0f1d6e1787d5630170db2b63e" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot 0.11.2", +] + +[[package]] +name = "futures-io" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" + +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" + +[[package]] +name = "futures-task" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" + +[[package]] +name = "futures-util" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generator" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc184cace1cea8335047a471cc1da80f18acf8a76f3bab2028d499e328948ec7" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", +] + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "ghash" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "gloo-timers" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "h2" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashlink" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" +dependencies = [ + "hashbrown 0.11.2", +] + +[[package]] +name = "hashlink" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" +dependencies = [ + "hashbrown 0.12.3", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "http" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "237a0714f28b1ee39ccec0770ccb544eb02c9ef2c82bb096230eefcffa6468b0" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "js-sys", + "once_cell", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "inlinable_string" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itertools" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8bf247779e67a9082a4790b45e71ac7cfd1321331a5c856a74a9faebdab78d0" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" + +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" + +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" + +[[package]] +name = "libsqlite3-sys" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "lock_api" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", + "value-bag", +] + +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "md-5" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b48670c893079d3c2ed79114e3644b7004df1c361a4e0ad52e2e6940d07c3d" +dependencies = [ + "digest", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "migration" +version = "0.1.0" +dependencies = [ + "async-std", + "sea-orm-migration", +] + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "minccino" +version = "0.1.0" +dependencies = [ + "base64", + "migration", + "rand", + "rocket", + "rocket_db_pools", + "sea-orm", + "sea-orm-rocket", + "serde", + "sha3", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "mio" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys", +] + +[[package]] +name = "multer" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a30ba6d97eb198c5e8a35d67d5779d6680cca35652a60ee90fc23dc431d4fde8" +dependencies = [ + "bytes", + "encoding_rs", + "futures-util", + "http", + "httparse", + "log", + "memchr", + "mime", + "spin 0.9.4", + "tokio", + "tokio-util", + "version_check", +] + +[[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + +[[package]] +name = "once_cell" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "os_str_bytes" +version = "6.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" + +[[package]] +name = "ouroboros" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbb50b356159620db6ac971c6d5c9ab788c9cc38a6f49619fca2a27acb062ca" +dependencies = [ + "aliasable", + "ouroboros_macro", +] + +[[package]] +name = "ouroboros_macro" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0d9d1a6191c4f391f87219d1ea42b23f09ee84d64763cd05ee6ea88d9f384d" +dependencies = [ + "Inflector", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "parking" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.5", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.3", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "paste" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" + +[[package]] +name = "pear" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e44241c5e4c868e3eaa78b7c1848cadd6344ed4f54d029832d32b415a58702" +dependencies = [ + "inlinable_string", + "pear_codegen", + "yansi", +] + +[[package]] +name = "pear_codegen" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82a5ca643c2303ecb740d506539deba189e16f2754040a42901cd8105d0282d0" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn", +] + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "pin-project" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + +[[package]] +name = "polling" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899b00b9c8ab553c743b3e11e87c5c7d423b2a2de229ba95b24a756344748011" +dependencies = [ + "autocfg", + "cfg-if", + "libc", + "log", + "wepoll-ffi", + "winapi", +] + +[[package]] +name = "polyval" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "postgres-protocol" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "878c6cbf956e03af9aa8204b407b9cbf47c072164800aa918c516cd4b056c50c" +dependencies = [ + "base64", + "byteorder", + "bytes", + "fallible-iterator", + "hmac", + "md-5", + "memchr", + "rand", + "sha2", + "stringprep", +] + +[[package]] +name = "postgres-types" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73d946ec7d256b04dfadc4e6a3292324e6f417124750fc5c0950f981b703a0f1" +dependencies = [ + "bytes", + "chrono", + "fallible-iterator", + "postgres-protocol", + "serde", + "serde_json", + "time", + "uuid", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-macro2-diagnostics" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "version_check", + "yansi", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + +[[package]] +name = "ref-cast" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed13bcd201494ab44900a96490291651d200730904221832b9547d24a87d332b" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5234cd6063258a5e32903b53b1b6ac043a0541c8adc1f610f67b0326c7a578fa" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "regex" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rocket" +version = "0.5.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ead083fce4a405feb349cf09abdf64471c6077f14e0ce59364aa90d4b99317" +dependencies = [ + "async-stream", + "async-trait", + "atomic", + "atty", + "binascii", + "bytes", + "either", + "figment", + "futures", + "indexmap", + "log", + "memchr", + "multer", + "num_cpus", + "parking_lot 0.12.1", + "pin-project-lite", + "rand", + "ref-cast", + "rocket_codegen", + "rocket_http", + "serde", + "serde_json", + "state", + "tempfile", + "time", + "tokio", + "tokio-stream", + "tokio-util", + "ubyte", + "version_check", + "yansi", +] + +[[package]] +name = "rocket_codegen" +version = "0.5.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6aeb6bb9c61e9cd2c00d70ea267bf36f76a4cc615e5908b349c2f9d93999b47" +dependencies = [ + "devise", + "glob", + "indexmap", + "proc-macro2", + "quote", + "rocket_http", + "syn", + "unicode-xid", +] + +[[package]] +name = "rocket_db_pools" +version = "0.1.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bc154f4f4985a136e2d59c336474a56da02103993f5e637e3a5424971ee4eff" +dependencies = [ + "rocket", + "rocket_db_pools_codegen", + "sqlx 0.5.13", + "version_check", +] + +[[package]] +name = "rocket_db_pools_codegen" +version = "0.1.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aa8f9b37bb1d4827aa5cca400d74e91d30f4352713cb65d6e7427bafe21336c" +dependencies = [ + "devise", + "quote", +] + +[[package]] +name = "rocket_http" +version = "0.5.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ded65d127954de3c12471630bf4b81a2792f065984461e65b91d0fdaafc17a2" +dependencies = [ + "cookie", + "either", + "futures", + "http", + "hyper", + "indexmap", + "log", + "memchr", + "pear", + "percent-encoding", + "pin-project-lite", + "ref-cast", + "serde", + "smallvec", + "stable-pattern", + "state", + "time", + "tokio", + "uncased", +] + +[[package]] +name = "rust_decimal" +version = "1.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee9164faf726e4f3ece4978b25ca877ddc6802fa77f38cdccb32c7f805ecd70c" +dependencies = [ + "arrayvec", + "num-traits", + "serde", +] + +[[package]] +name = "rustls" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" +dependencies = [ + "base64", + "log", + "ring", + "sct 0.6.1", + "webpki 0.21.4", +] + +[[package]] +name = "rustls" +version = "0.20.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" +dependencies = [ + "log", + "ring", + "sct 0.7.0", + "webpki 0.22.0", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" +dependencies = [ + "base64", +] + +[[package]] +name = "rustversion" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" + +[[package]] +name = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sct" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sea-orm" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "089dcca5d2c8393f5f21c7f7b0d84062839c3264ba62dcc0043eb207862e13a1" +dependencies = [ + "async-stream", + "async-trait", + "chrono", + "futures", + "futures-util", + "log", + "once_cell", + "ouroboros", + "rust_decimal", + "sea-orm-macros", + "sea-query", + "sea-strum", + "serde", + "serde_json", + "sqlx 0.6.2", + "time", + "tracing", + "url", + "uuid", +] + +[[package]] +name = "sea-orm-cli" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cefd2d8878bd7e8b7313f036725fa3d08585d101fb1bf3adca7fc13f553f906" +dependencies = [ + "async-std", + "chrono", + "clap", + "dotenv", + "regex", + "sea-schema", + "tracing", + "tracing-subscriber", + "url", +] + +[[package]] +name = "sea-orm-macros" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d9708f945febe8625ccb0334654b97d1a1a0bffa0473d86e6108ad13f79bd5" +dependencies = [ + "bae", + "heck 0.3.3", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sea-orm-migration" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a28587780fbae5c414a62bf0b32405f9da2e000d94f426abf214b2b2e68631" +dependencies = [ + "async-trait", + "clap", + "dotenv", + "sea-orm", + "sea-orm-cli", + "sea-schema", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "sea-orm-rocket" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29427b7598f825f6640f608bc4d134e39994a6c4812b2225e33d8b2c6e10a14f" +dependencies = [ + "rocket", + "sea-orm-rocket-codegen", +] + +[[package]] +name = "sea-orm-rocket-codegen" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfd750adb2541f30b855e2d86e90bf7031ac17e048ac5226a8e8c8d8a6022f2" +dependencies = [ + "devise", + "quote", +] + +[[package]] +name = "sea-query" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a1de9d0334895f7eb51bd1603c3c9f6737413f905a134001f1e198f43bfd70" +dependencies = [ + "chrono", + "postgres-types", + "rust_decimal", + "sea-query-derive", + "sea-query-driver", + "serde_json", + "time", + "uuid", +] + +[[package]] +name = "sea-query-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cdc022b4f606353fe5dc85b09713a04e433323b70163e81513b141c6ae6eb5" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "syn", + "thiserror", +] + +[[package]] +name = "sea-query-driver" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d7f0cae2e7ebb2affc378c40bc343c8197181d601d6755c3e66f1bd18cac253" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sea-schema" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f737a6819fcad9727207d7090ccd6a33c0b384f3794e8838f952b52d599e3a17" +dependencies = [ + "futures", + "sea-query", + "sea-schema-derive", +] + +[[package]] +name = "sea-schema-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56821b7076f5096b8f726e2791ad255a99c82498e08ec477a65a96c461ff1927" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sea-strum" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391d06a6007842cfe79ac6f7f53911b76dfd69fc9a6769f1cf6569d12ce20e1b" +dependencies = [ + "sea-strum_macros", +] + +[[package]] +name = "sea-strum_macros" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b4397b825df6ccf1e98bcdabef3bbcfc47ff5853983467850eeab878384f21" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "serde" +version = "1.0.144" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.144" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9db03534dff993187064c4e0c05a5708d2a9728ace9a8959b77bedf415dac5" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaedf34ed289ea47c2b741bb72e5357a209512d67bcd4bda44359e5bf0470f56" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" + +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" +dependencies = [ + "lock_api", +] + +[[package]] +name = "sqlformat" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" +dependencies = [ + "itertools", + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlformat" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87e292b4291f154971a43c3774364e2cbcaec599d3f5bf6fa9d122885dbc38a" +dependencies = [ + "itertools", + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "551873805652ba0d912fec5bbb0f8b4cdd96baf8e2ebf5970e5671092966019b" +dependencies = [ + "sqlx-core 0.5.13", + "sqlx-macros 0.5.13", +] + +[[package]] +name = "sqlx" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9249290c05928352f71c077cc44a464d880c63f26f7534728cca008e135c0428" +dependencies = [ + "sqlx-core 0.6.2", + "sqlx-macros 0.6.2", +] + +[[package]] +name = "sqlx-core" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48c61941ccf5ddcada342cd59e3e5173b007c509e1e8e990dafc830294d9dc5" +dependencies = [ + "ahash", + "atoi 0.4.0", + "bitflags", + "byteorder", + "bytes", + "crossbeam-queue", + "either", + "event-listener", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "hashlink 0.7.0", + "hex", + "indexmap", + "itoa", + "libc", + "libsqlite3-sys", + "log", + "memchr", + "once_cell", + "paste", + "percent-encoding", + "rustls 0.19.1", + "smallvec", + "sqlformat 0.1.8", + "sqlx-rt 0.5.13", + "stringprep", + "thiserror", + "tokio-stream", + "url", + "webpki 0.21.4", + "webpki-roots 0.21.1", +] + +[[package]] +name = "sqlx-core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbc16ddba161afc99e14d1713a453747a2b07fc097d2009f4c300ec99286105" +dependencies = [ + "ahash", + "atoi 1.0.0", + "bitflags", + "byteorder", + "bytes", + "chrono", + "crc", + "crossbeam-queue", + "dotenvy", + "either", + "event-listener", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "hashlink 0.8.1", + "hex", + "indexmap", + "itoa", + "libc", + "libsqlite3-sys", + "log", + "memchr", + "num-bigint", + "once_cell", + "paste", + "percent-encoding", + "rust_decimal", + "rustls 0.20.6", + "rustls-pemfile", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlformat 0.2.0", + "sqlx-rt 0.6.2", + "stringprep", + "thiserror", + "time", + "tokio-stream", + "url", + "uuid", + "webpki-roots 0.22.4", +] + +[[package]] +name = "sqlx-macros" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0fba2b0cae21fc00fe6046f8baa4c7fcb49e379f0f592b04696607f69ed2e1" +dependencies = [ + "dotenv", + "either", + "heck 0.4.0", + "once_cell", + "proc-macro2", + "quote", + "sqlx-core 0.5.13", + "sqlx-rt 0.5.13", + "syn", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b850fa514dc11f2ee85be9d055c512aa866746adfacd1cb42d867d68e6a5b0d9" +dependencies = [ + "dotenvy", + "either", + "heck 0.4.0", + "once_cell", + "proc-macro2", + "quote", + "serde_json", + "sha2", + "sqlx-core 0.6.2", + "sqlx-rt 0.6.2", + "syn", + "url", +] + +[[package]] +name = "sqlx-rt" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4db708cd3e459078f85f39f96a00960bd841f66ee2a669e90bf36907f5a79aae" +dependencies = [ + "once_cell", + "tokio", + "tokio-rustls 0.22.0", +] + +[[package]] +name = "sqlx-rt" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24c5b2d25fa654cc5f841750b8e1cdedbe21189bf9a9382ee90bfa9dd3562396" +dependencies = [ + "once_cell", + "tokio", + "tokio-rustls 0.23.4", +] + +[[package]] +name = "stable-pattern" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4564168c00635f88eaed410d5efa8131afa8d8699a612c80c455a0ba05c21045" +dependencies = [ + "memchr", +] + +[[package]] +name = "state" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbe866e1e51e8260c9eed836a042a5e7f6726bb2b411dffeaa712e19c388f23b" +dependencies = [ + "loom", +] + +[[package]] +name = "stringprep" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" + +[[package]] +name = "thiserror" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b" +dependencies = [ + "itoa", + "libc", + "num_threads", + "time-macros", +] + +[[package]] +name = "time-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "1.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89797afd69d206ccd11fb0ea560a44bbb87731d020670e79416d442919257d42" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +dependencies = [ + "rustls 0.19.1", + "tokio", + "webpki 0.21.4", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls 0.20.6", + "tokio", + "webpki 0.22.0", +] + +[[package]] +name = "tokio-stream" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +dependencies = [ + "serde", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" +dependencies = [ + "ansi_term", + "matchers", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "ubyte" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c81f0dae7d286ad0d9366d7679a77934cfc3cf3a8d67e82669794412b2368fe6" +dependencies = [ + "serde", +] + +[[package]] +name = "uncased" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" +dependencies = [ + "serde", + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" + +[[package]] +name = "unicode-xid" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "uuid" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f" +dependencies = [ + "getrandom", + "serde", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "value-bag" +version = "1.0.0-alpha.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" +dependencies = [ + "ctor", + "version_check", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "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 = "wasm-bindgen" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + +[[package]] +name = "web-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" +dependencies = [ + "webpki 0.21.4", +] + +[[package]] +name = "webpki-roots" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1c760f0d366a6c24a02ed7816e23e691f5d92291f94d15e836006fd11b04daf" +dependencies = [ + "webpki 0.22.0", +] + +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbedf6db9096bc2364adce0ae0aa636dcd89f3c3f2cd67947062aaf0ca2a10ec" +dependencies = [ + "windows_aarch64_msvc 0.32.0", + "windows_i686_gnu 0.32.0", + "windows_i686_msvc 0.32.0", + "windows_x86_64_gnu 0.32.0", + "windows_x86_64_msvc 0.32.0", +] + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a2615d1 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,20 @@ +[workspace] +members = [".", "migration"] + +[package] +name = "minccino" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rocket = {version = "0.5.0-rc.2", features = ["json"]} +rocket_db_pools = {version = "0.1.0-rc.2", features = ["sqlx_sqlite"]} +sea-orm = {version = "^0", features = [ "sqlx-sqlite", "runtime-tokio-rustls", "macros" ]} +serde = "1" +sha3 = "0.10" +rand = "0.8.5" +base64 = "0.13.0" +sea-orm-rocket = "0.5.0" +migration = { path = "./migration" } \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..70cb7f2 --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +# minccino - Lightweight cloud-init server + +Server application that provides cloud-init metadata via the `nocloud-net` provider. Uses the link-local IPv6 address for "authentication" by pulling MAC address information. + +## Requirements + +Only sqlite3 dev libraries are required for Diesel. + +## Configuration + +Configuration is handled either via `minccino.toml` or `MINCCINO_` environment variables. To use the API (required for managing instances), you'll need to generate an API key and relevant hash in the config file. To generate this, run: + +``` +minccino genkey +``` + +This outputs the API key and the relevant config snippet you'll need to add to `minccino.toml` for the key. + +## API Usage + +All API endpoints require an `X-API-Key` header with the key generated above, and for the API client to be connected via localhost. \todo Allow overriding the latter requirement, if needed + +To create an instance (all requests sent to `http://[::1]`): +``` +> POST /_yui/instances HTTP/1.1 +> X-API-Key: Your_API_Key +> Content-type: application/json +> [...] +> +> { +> "name": "instance_hostname", +> "os_name": "netbsd|debian|invalid", +> "mac_address": "0a:42:01:23:45:67" +> } +> +< HTTP/1.1 201 Created +< Content-type: application/json +< [...] +< +< { +< "error": null, +< "instances": [ +< { +< "id": 591750913, +< "name": "instance_hostname", +< "os_name": "netbsd|debian|invalid", +< "mac_address": "0a:42:01:23:45:67" +< } +< ] +< } +} +``` \ No newline at end of file diff --git a/migration/Cargo.toml b/migration/Cargo.toml new file mode 100644 index 0000000..28e4376 --- /dev/null +++ b/migration/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "migration" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +name = "migration" +path = "src/lib.rs" + +[dependencies] +async-std = { version = "^1", features = ["attributes", "tokio1"] } + +[dependencies.sea-orm-migration] +version = "^0.9.0" +features = [ + "runtime-tokio-rustls", + "sqlx-sqlite", +] diff --git a/migration/README.md b/migration/README.md new file mode 100644 index 0000000..b3ea53e --- /dev/null +++ b/migration/README.md @@ -0,0 +1,41 @@ +# Running Migrator CLI + +- Generate a new migration file + ```sh + cargo run -- migrate generate MIGRATION_NAME + ``` +- Apply all pending migrations + ```sh + cargo run + ``` + ```sh + cargo run -- up + ``` +- Apply first 10 pending migrations + ```sh + cargo run -- up -n 10 + ``` +- Rollback last applied migrations + ```sh + cargo run -- down + ``` +- Rollback last 10 applied migrations + ```sh + cargo run -- down -n 10 + ``` +- Drop all tables from the database, then reapply all migrations + ```sh + cargo run -- fresh + ``` +- Rollback all applied migrations, then reapply all migrations + ```sh + cargo run -- refresh + ``` +- Rollback all applied migrations + ```sh + cargo run -- reset + ``` +- Check the status of all migrations + ```sh + cargo run -- status + ``` diff --git a/migration/src/lib.rs b/migration/src/lib.rs new file mode 100644 index 0000000..96b8b5b --- /dev/null +++ b/migration/src/lib.rs @@ -0,0 +1,12 @@ +pub use sea_orm_migration::prelude::*; + +mod m20220919_122233_create_instance_data; + +pub struct Migrator; + +#[async_trait::async_trait] +impl MigratorTrait for Migrator { + fn migrations() -> Vec> { + vec![Box::new(m20220919_122233_create_instance_data::Migration)] + } +} diff --git a/migration/src/m20220919_122233_create_instance_data.rs b/migration/src/m20220919_122233_create_instance_data.rs new file mode 100644 index 0000000..2f29c2e --- /dev/null +++ b/migration/src/m20220919_122233_create_instance_data.rs @@ -0,0 +1,69 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(Defaults::Table) + .if_not_exists() + .col( + ColumnDef::new(Defaults::Key) + .string() + .not_null() + .primary_key(), + ) + .col(ColumnDef::new(Defaults::Value).string().not_null()) + .to_owned(), + ) + .await?; + manager + .create_table( + Table::create() + .table(InstanceInfo::Table) + .if_not_exists() + .col( + ColumnDef::new(InstanceInfo::Id) + .big_integer() + .not_null() + .primary_key(), + ) + .col(ColumnDef::new(InstanceInfo::Hostname).string().not_null()) + .col(ColumnDef::new(InstanceInfo::MacAddress).string().not_null()) + .col(ColumnDef::new(InstanceInfo::SshKeys).string()) + .col(ColumnDef::new(InstanceInfo::UserData).binary()) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(Defaults::Table).to_owned()) + .await?; + manager + .drop_table(Table::drop().table(InstanceInfo::Table).to_owned()) + .await + } +} + +#[derive(Iden)] +enum InstanceInfo { + Table, + Id, + Hostname, + MacAddress, + SshKeys, + UserData, +} + +#[derive(Iden)] +enum Defaults { + Table, + Key, + Value, +} diff --git a/migration/src/main.rs b/migration/src/main.rs new file mode 100644 index 0000000..c6b6e48 --- /dev/null +++ b/migration/src/main.rs @@ -0,0 +1,6 @@ +use sea_orm_migration::prelude::*; + +#[async_std::main] +async fn main() { + cli::run_cli(migration::Migrator).await; +} diff --git a/minccino.toml.example b/minccino.toml.example new file mode 100644 index 0000000..f093404 --- /dev/null +++ b/minccino.toml.example @@ -0,0 +1,16 @@ +[default] +address = "::" +port = 80 + +[debug] +workers = 4 +log_level = "debug" +limits = { forms = 32768 } + +[release] +port = 80 +log_level = "normal" +cli_colors = false + +[default.databases.instances] +url = "db.sql" \ No newline at end of file diff --git a/src/db.rs b/src/db.rs new file mode 100644 index 0000000..1967b8d --- /dev/null +++ b/src/db.rs @@ -0,0 +1,27 @@ +use rocket::async_trait; +use rocket_db_pools::{rocket::figment::Figment, Config, Database}; + +#[derive(Debug, Clone)] +pub struct InstDbConn { + pub conn: sea_orm::DatabaseConnection, +} + +#[async_trait] +impl rocket_db_pools::Pool for InstDbConn { + type Error = sea_orm::DbErr; + type Connection = sea_orm::DatabaseConnection; + + async fn init(figment: &Figment) -> Result { + let config = figment.extract::().unwrap(); + let conn = sea_orm::Database::connect(&config.url).await.unwrap(); + Ok(Self { conn }) + } + + async fn get(&self) -> Result { + Ok(self.conn.clone()) + } +} + +#[derive(Database, Debug)] +#[database("instances")] +pub struct Instances(InstDbConn); diff --git a/src/entity/defaults.rs b/src/entity/defaults.rs new file mode 100644 index 0000000..fb090a2 --- /dev/null +++ b/src/entity/defaults.rs @@ -0,0 +1,23 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.9.2 + +use crate::types::DefaultKey; +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] +#[sea_orm(table_name = "defaults")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub key: DefaultKey, + pub value: String, +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation {} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + panic!("No RelationDef") + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/entity/instance_info.rs b/src/entity/instance_info.rs new file mode 100644 index 0000000..6f52585 --- /dev/null +++ b/src/entity/instance_info.rs @@ -0,0 +1,26 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.9.2 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Serialize, Deserialize)] +#[sea_orm(table_name = "instance_info")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: u32, + pub hostname: String, + pub mac_address: String, + pub ssh_keys: Option, + pub user_data: Option>, +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation {} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + panic!("No RelationDef") + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/entity/mod.rs b/src/entity/mod.rs new file mode 100644 index 0000000..0b3741b --- /dev/null +++ b/src/entity/mod.rs @@ -0,0 +1,2 @@ +pub mod defaults; +pub mod instance_info; diff --git a/src/llv6.rs b/src/llv6.rs new file mode 100644 index 0000000..571ace2 --- /dev/null +++ b/src/llv6.rs @@ -0,0 +1,49 @@ +use rocket::{ + http::Status, + request::{FromRequest, Outcome, Request}, +}; +use std::net::IpAddr; + +use crate::types::MacAddr; + +pub struct ClientEUI64 { + pub mac_address: MacAddr, +} + +#[derive(Debug)] +pub enum EUI64Error { + NotIPV6, + NotEUI64, + InvalidMACAddr, +} + +#[rocket::async_trait] +impl<'r> FromRequest<'r> for ClientEUI64 { + type Error = EUI64Error; + + async fn from_request(request: &'r Request<'_>) -> Outcome { + let client_ip = match request.client_ip() { + Some(IpAddr::V6(ip)) => ip, + _ => return Outcome::Failure((Status::Forbidden, EUI64Error::NotIPV6)), + }; + if client_ip.segments()[0] == 0xfe80 { + let octets = client_ip.octets(); + let mut mac = [&octets[8..11], &octets[13..]].concat(); + mac[0] ^= 0x2; + let mac: [u8; 6] = match mac.try_into() { + Ok(t) => t, + Err(_) => { + return Outcome::Failure(( + Status::InternalServerError, + EUI64Error::InvalidMACAddr, + )) + } + }; + return Outcome::Success(ClientEUI64 { + mac_address: MacAddr(mac), + }); + } else { + return Outcome::Failure((Status::Forbidden, EUI64Error::NotEUI64)); + } + } +} diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..210076b --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,21 @@ +macro_rules! api_err { + ( $resp:ident, $($arg:tt)* ) => { + APIError::$resp( + Json($crate::yui::ErrorResponse { + error: format!( $($arg)* ), + })) + }; +} + +macro_rules! hex { + ($arg:expr) => {{ + $arg.map(|u| format!("{:x}", u)) + .collect::>() + .into_iter() + .as_slice() + .join("") + }}; +} + +pub(crate) use api_err; +pub(crate) use hex; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..a61096c --- /dev/null +++ b/src/main.rs @@ -0,0 +1,78 @@ +#[macro_use] +extern crate rocket; + +mod entity; +#[macro_use] +mod macros; +mod db; +mod llv6; +mod meta; +#[cfg(test)] +mod test; +mod types; +mod yui; + +use db::Instances; +use migration::{Migrator, MigratorTrait}; +use rocket::figment::providers::{Env, Format, Toml}; +use rocket::Build; +use rocket::Rocket; +use rocket_db_pools::Database; + +fn rocket() -> Rocket { + let rocket = rocket::build() + .attach(Instances::init()) + .mount("/", meta::routes::all()) + .mount("/_yui/", yui::routes::all()); + #[cfg(test)] + let figment = { + std::env::set_var( + "MINCCINO_TEST_DATABASES", + "{instances={url=\"sqlite::memory:\"}}", + ); + rocket::figment::Figment::from(rocket::Config::default()) + .merge(Toml::file("minccino.toml").nested()) + .merge(Env::prefixed("MINCCINO_TEST_")) + }; + #[cfg(not(test))] + let figment = { + rocket::figment::Figment::from(rocket::Config::default()) + .merge(Toml::file("minccino.toml").nested()) + .merge(Env::prefixed("MINCCINO_")) + }; + rocket + .configure(figment) + .attach(rocket::fairing::AdHoc::on_liftoff( + "Apply migrations, if needed", + |rocket| { + Box::pin(async move { + if let Some(db) = Instances::fetch(rocket) { + Migrator::up(&db.conn, None).await.unwrap(); + } + }) + }, + )) +} + +#[rocket::main] +async fn main() -> Result<(), rocket::Error> { + let arg = std::env::args().nth(1); + match arg { + Some(x) => match x.as_str() { + "genkey" => { + let (key, hash) = yui::auth::genkey(); + + println!("\n# API Key: {}\n", key); + println!( + "# Put the following in your Rocket.toml:\n[minccino]\napi_hash = \"{}\"", + hash + ); + } + _ => println!("not implemented"), + }, + None => { + let _rocket = rocket().ignite().await?.launch().await?; + } + } + Ok(()) +} diff --git a/src/meta/mod.rs b/src/meta/mod.rs new file mode 100644 index 0000000..47b857a --- /dev/null +++ b/src/meta/mod.rs @@ -0,0 +1,23 @@ +pub mod routes; +#[cfg(test)] +mod test; +use rocket::serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +#[serde(crate = "rocket::serde", rename_all = "kebab-case")] +pub struct CIMetadata { + pub instance_id: String, + pub local_hostname: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub public_keys: Option>, +} + +#[derive(Debug, Responder)] +pub enum MetaError { + #[response(status = 404)] + NotFound(()), + #[response(status = 500)] + InternalServerError(()), +} + +type MetaResponse = Result; diff --git a/src/meta/routes.rs b/src/meta/routes.rs new file mode 100644 index 0000000..0344e52 --- /dev/null +++ b/src/meta/routes.rs @@ -0,0 +1,60 @@ +use crate::db::Instances; +use crate::entity::*; +use crate::llv6::*; +use crate::meta::*; +use crate::types::DefaultKey; +use rocket::serde::json::Json; +use rocket_db_pools::Connection; +use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; + +/// standard cloud-init metadata +#[get("/meta-data")] +pub async fn metadata( + db: Connection, + client_addr: ClientEUI64, +) -> MetaResponse> { + match instance_info::Entity::find() + .filter(instance_info::Column::MacAddress.eq(client_addr.mac_address.to_string())) + .one(&*db) + .await + { + Ok(Some(v)) => Ok(Json(CIMetadata { + instance_id: format!("i-{:x}", v.id), + local_hostname: v.hostname, + public_keys: { + match v.ssh_keys { + Some(keys) => Some(keys), + // no keys for instance -> try to get from defaults + None => defaults::Entity::find_by_id(DefaultKey::SshKeys) + .one(&*db) + .await + .map_err(|_| MetaError::InternalServerError(()))? + .map(|x| x.value), + } + .map(|k| k.split('\n').map(|s| s.to_owned()).collect()) + }, + })), + _ => Err(MetaError::NotFound(())), + } +} + +/// standard cloud-init userdata +#[get("/user-data")] +pub async fn userdata( + db: Connection, + client_addr: ClientEUI64, +) -> MetaResponse> { + match instance_info::Entity::find() + .filter(instance_info::Column::MacAddress.eq(client_addr.mac_address.to_string())) + .one(&*db) + .await + .map_err(|_| MetaError::InternalServerError(()))? + { + Some(v) => v.user_data.map_or(Err(MetaError::NotFound(())), Ok), + None => Err(MetaError::NotFound(())), + } +} + +pub fn all() -> Vec { + routes![metadata, userdata,] +} diff --git a/src/meta/test.rs b/src/meta/test.rs new file mode 100644 index 0000000..79b8a18 --- /dev/null +++ b/src/meta/test.rs @@ -0,0 +1,186 @@ +use super::routes::*; +use crate::meta::CIMetadata; +use crate::rocket; +use crate::test::*; +use crate::types::MacAddr; +use crate::yui::routes::*; +use crate::yui::InstanceReq; +use crate::yui::InstanceResponse; +use rocket::http::{ContentType, Header, Status}; +use rocket::local::blocking::Client; +use std::net::{Ipv6Addr, SocketAddr, SocketAddrV6}; + +#[test] +fn metadata_works() { + let client = Client::tracked(rocket()).expect("valid rocket instance"); + + let instance = InstanceReq { + name: "first-test".to_owned(), + mac_address: MacAddr(LLV6_MAC).to_string(), + ssh_keys: None, + user_data: None, + }; + let response = client + .post(uri!("/_yui/", new_instance())) + .header(Header::new("x-api-key", SNAKEOIL_KEY)) + .remote(saddr6!(localhost)) + .json(&instance) + .dispatch(); + assert_eq!(response.status(), Status::Ok); + + let inst = response + .into_json::() + .expect("json in InstanceResponse format"); + let inst = inst.instances.unwrap()[0].clone(); + + let metadata = client + .get(uri!(metadata())) + .remote(saddr6!(LLV6_IP)) + .dispatch(); + assert_eq!(metadata.status(), Status::Ok); + + let metadata = metadata + .into_json::() + .expect("json in form CIMetadata"); + + assert_eq!(metadata.local_hostname, instance.name); + + let response = client + .delete(uri!("/_yui/", delete_instance(inst.id))) + .header(Header::new("x-api-key", SNAKEOIL_KEY)) + .remote(saddr6!(localhost)) + .dispatch(); + assert_eq!(response.status(), Status::Ok); +} + +#[test] +fn metadata_defaults_apply() { + const SNAKEOIL_SSHKEY: &str = + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJg6JbxdLaFpG0vnXHV0kNoz282vgjtJlcvGv5DUDKJj snakeoil"; + const INSTANCE_SSHKEY: &str = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGPxtsgJzSNTQAsv0LV7usNOP8CBmCoqD8AkwZUvE01E instance-key"; + let client = Client::tracked(rocket()).expect("valid rocket instance"); + + let keys = SNAKEOIL_SSHKEY.to_owned(); + + let response = client + .post(uri!("/_yui/", set_defaults("ssh_keys"))) + .header(ContentType::Plain) + .header(Header::new("x-api-key", SNAKEOIL_KEY)) + .remote(saddr6!(localhost)) + .body(keys) + .dispatch(); + + assert_eq!( + response.status(), + Status::Ok, + "Couldn't set defaults: (code {}) {:?}", + response.status().code, + response.into_string() + ); + + // create the first instance, with no ssh keys + let instance = InstanceReq { + name: "first-test".to_owned(), + mac_address: LLV6_MACSTR.to_owned(), + ssh_keys: None, + user_data: None, + }; + + let response = client + .post(uri!("/_yui/", new_instance())) + .json(&instance) + .header(Header::new("x-api-key", SNAKEOIL_KEY)) + .remote(saddr6!(localhost)) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + + let response = client + .get(uri!(metadata())) + .remote(saddr6!(LLV6_IP)) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + + let response = response + .into_json::() + .expect("should be instance metadata"); + + let keys = response + .public_keys + .expect("should be a vec of SSH public keys"); + + assert_eq!(keys.len(), 1); + assert_eq!(keys[0], SNAKEOIL_SSHKEY); + + // new instance, with defined ssh keys + let instance = InstanceReq { + name: "second-test".to_owned(), + mac_address: LLV6_MACSTR2.to_owned(), + ssh_keys: Some(vec![INSTANCE_SSHKEY.to_owned()]), + user_data: None, + }; + + let response = client + .post(uri!("/_yui/", new_instance())) + .json(&instance) + .header(Header::new("x-api-key", SNAKEOIL_KEY)) + .remote(saddr6!(localhost)) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + + let response = client + .get(uri!(metadata())) + .remote(saddr6!(LLV6_IP2)) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + + let response = response + .into_json::() + .expect("should be instance metadata"); + + let keys = response + .public_keys + .expect("should be a vec of SSH public keys"); + + assert_eq!(keys[0], INSTANCE_SSHKEY); +} + +#[test] +fn userdata_works() { + let client = Client::tracked(rocket()).expect("valid rocket instance"); + + // create instance + let instance = InstanceReq { + name: "first-test".to_owned(), + mac_address: MacAddr(LLV6_MAC).to_string(), + ssh_keys: None, + user_data: Some(base64::encode(SPEEX)), + }; + let response = client + .post(uri!("/_yui/", new_instance())) + .header(Header::new("x-api-key", SNAKEOIL_KEY)) + .remote(saddr6!(localhost)) + .json(&instance) + .dispatch(); + assert_eq!(response.status(), Status::Ok); + + // get userdata + let userdata = client + .get(uri!(userdata())) + .remote(saddr6!(LLV6_IP)) + .dispatch(); + + assert_eq!(userdata.status(), Status::Ok); + assert_eq!(userdata.into_string().unwrap(), SPEEX); + + // make sure only LLV6_IP can access it + let bad_userdata = client + .get(uri!(userdata())) + .remote(saddr6!(LLV6_IP2)) + .dispatch(); + + assert_eq!(bad_userdata.status(), Status::NotFound); +} diff --git a/src/test.rs b/src/test.rs new file mode 100644 index 0000000..f25a83f --- /dev/null +++ b/src/test.rs @@ -0,0 +1,25 @@ +use std::net::Ipv6Addr; + +pub const SNAKEOIL_KEY: &str = "I3QleS8dm9cWUdzOL5m--C3qRNn-a2rh8h9zzcAy9q5o4dWF"; +pub const SNAKEOIL_HASH: &str = "bbdd8c34a583554b4a20f7b0d92f1c3f5affdfbdd768b63c2945a63195c24a"; + +pub const LLV6_IP: Ipv6Addr = Ipv6Addr::new(0xfe80, 0, 0, 0, 0x0042, 0xafff, 0xfe32, 0xa0fe); +pub const LLV6_MAC: [u8; 6] = [0x02, 0x42, 0xaf, 0x32, 0xa0, 0xfe]; +pub const LLV6_MACSTR: &str = "02:42:af:32:a0:fe"; + +pub const LLV6_IP2: Ipv6Addr = Ipv6Addr::new(0xfe80, 0, 0, 0, 0x0842, 0xafff, 0xfe64, 0x69ba); +pub const LLV6_MAC2: [u8; 6] = [0x0a, 0x42, 0xaf, 0x64, 0x69, 0xba]; +pub const LLV6_MACSTR2: &str = "0a:42:af:64:69:ba"; + +pub const SPEEX: &str = "This is not an example of Speex, an audio compression codec specifically tuned for the reproduction of human speech."; + +macro_rules! saddr6 { + (localhost) => { + SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 8080, 0, 0)) + }; + ($addr:expr) => { + SocketAddr::V6(SocketAddrV6::new($addr, 8080, 0, 0)) + }; +} + +pub(crate) use saddr6; diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 0000000..e634504 --- /dev/null +++ b/src/types.rs @@ -0,0 +1,84 @@ +use std::{convert::TryFrom, fmt}; + +use sea_orm::prelude::*; +use std::ops::{Deref, Index}; + +pub enum MacParseError { + BadOctet, + WrongOctetCount, +} + +/// Wrapper type for validation and manipulation of MAC addresses +pub struct MacAddr(pub [u8; 6]); + +impl TryFrom for MacAddr { + type Error = MacParseError; + fn try_from(value: String) -> Result { + let v = value + .split(':') + .map(|x| u8::from_str_radix(x, 16)) + .collect::, _>>() + .map_err(|_| Self::Error::BadOctet)?; + let octets: [u8; 6] = v.try_into().map_err(|_| Self::Error::WrongOctetCount)?; + + Ok(Self(octets)) + } +} + +impl fmt::Display for MacAddr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0.map(|x| format!("{:x}", x)).join(":")) + } +} + +impl Deref for MacAddr { + type Target = [u8; 6]; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Index for MacAddr { + type Output = u8; + fn index(&self, index: usize) -> &Self::Output { + &self.0[index] + } +} + +/// Key for defaults table +#[derive(Clone, Copy, Debug, EnumIter, PartialEq, Eq, DeriveActiveEnum)] +#[sea_orm(rs_type = "String", db_type = "Text")] +pub enum DefaultKey { + #[sea_orm(string_value = "ssh_keys")] + SshKeys, +} + +impl sea_orm::TryFromU64 for DefaultKey { + fn try_from_u64(_: u64) -> Result { + // XXX: ok im being a bit lazy here. it's prolly fine + Err(DbErr::Type("?????".to_owned())) + } +} + +impl fmt::Display for DefaultKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::SshKeys => write!(f, "ssh_keys"), + } + } +} + +#[derive(Debug)] +pub enum ParseError { + InvalidKey, +} + +impl TryFrom for DefaultKey { + type Error = ParseError; + fn try_from(value: String) -> Result { + match value.as_str() { + "ssh_keys" => Ok(Self::SshKeys), + _ => Err(ParseError::InvalidKey), + } + } +} diff --git a/src/yui/auth.rs b/src/yui/auth.rs new file mode 100644 index 0000000..da506e7 --- /dev/null +++ b/src/yui/auth.rs @@ -0,0 +1,103 @@ +use crate::macros::hex; +#[cfg(test)] +use crate::test::SNAKEOIL_HASH; +use rocket::{ + http::Status, + request::{FromRequest, Outcome, Request}, +}; +use sha3::{Digest, Sha3_256}; + +/// Generate an API Key and its hash +pub fn genkey() -> (String, String) { + let apikey = { + let bytes: Vec = (0..36).map(|_| rand::random::()).collect(); + base64::encode(bytes).replace('+', "-").replace('/', "_") + }; + let apihash = { + let mut hasher = Sha3_256::default(); + hasher.update(&apikey); + hex!(hasher.finalize().iter()) + }; + (apikey, apihash) +} + +#[derive(Debug)] +pub enum LoginError { + UnknownClientIP, + WrongClientIP, + WrongKey, + #[allow(dead_code)] + ConfigError(String), +} + +/// Extra app config data +#[derive(rocket::serde::Deserialize)] +#[serde(crate = "rocket::serde")] +pub struct MinccinoConfig { + api_hash: String, +} + +/// Confirms a vaid API key is being used, and blocks non-localhost requests +pub struct APIUser { + _priv: (), +} + +#[rocket::async_trait] +impl<'r> FromRequest<'r> for APIUser { + type Error = LoginError; + + async fn from_request(request: &'r Request<'_>) -> Outcome { + // get the request ip, and check if it's localhost + let client_ip = match request.client_ip() { + Some(ip) => ip, + _ => return Outcome::Failure((Status::Forbidden, LoginError::UnknownClientIP)), + }; + + if !client_ip.is_loopback() { + return Outcome::Failure((Status::Forbidden, LoginError::WrongClientIP)); + } + + // get the API key from X-API-Key + let key_header = request.headers().get("x-api-key").collect::>(); + let apikey = match key_header.len() { + 1 => key_header[0], + _ => return Outcome::Failure((Status::Unauthorized, LoginError::WrongKey)), + }; + + // get api key hash from config + #[cfg(test)] + let app_config: MinccinoConfig = { + warn!("/!\\ /!\\ FAKE API KEY IN USE /!\\ /!\\"); + warn!("IF YOU SEE THIS IN PROD, SOMETHING IS VERY WRONG"); + + MinccinoConfig { + api_hash: String::from(SNAKEOIL_HASH), + } + }; + #[cfg(not(test))] + let app_config: MinccinoConfig = match request.rocket().figment().extract_inner("minccino") + { + Ok(conf) => conf, + Err(err) => { + return Outcome::Failure(( + Status::InternalServerError, + LoginError::ConfigError(format!("{:?}", err)), + )) + } + }; + + let apihash = { + let mut hasher = Sha3_256::default(); + hasher.update(apikey.as_bytes()); + hex!(hasher.finalize().iter()) + }; + + // make sure the hashed API key matches what we've got + if app_config.api_hash != apihash { + return Outcome::Failure((Status::Forbidden, LoginError::WrongKey)); + } + + // and we're good! + Outcome::Success(APIUser { _priv: () }) + } +} diff --git a/src/yui/mod.rs b/src/yui/mod.rs new file mode 100644 index 0000000..6efbd62 --- /dev/null +++ b/src/yui/mod.rs @@ -0,0 +1,49 @@ +use crate::entity::*; +use rocket::serde::{json::Json, Deserialize, Serialize}; + +pub mod auth; +pub mod routes; +#[cfg(test)] +mod test; + +#[derive(Serialize, Deserialize)] +#[serde(crate = "rocket::serde")] +pub struct InstanceReq { + pub name: String, + pub mac_address: String, + pub ssh_keys: Option>, + pub user_data: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(crate = "rocket::serde")] +pub struct InstanceResponse { + pub error: Option, + pub instances: Option>, +} + +impl InstanceResponse { + pub fn new(inst: Vec) -> Self { + InstanceResponse { + error: None, + instances: Some(inst), + } + } +} +#[derive(Debug, Serialize, Deserialize)] +#[serde(crate = "rocket::serde")] +pub struct ErrorResponse { + pub error: String, +} + +#[derive(Debug, Responder)] +pub enum APIError { + #[response(status = 400)] + BadRequest(Json), + #[response(status = 404)] + NotFound(Json), + #[response(status = 409)] + Conflict(Json), + #[response(status = 500)] + InternalServerError(Json), +} diff --git a/src/yui/routes.rs b/src/yui/routes.rs new file mode 100644 index 0000000..d891186 --- /dev/null +++ b/src/yui/routes.rs @@ -0,0 +1,207 @@ +use std::convert::TryInto; + +use crate::entity::*; +use crate::macros::api_err; +use crate::types::MacAddr; +use crate::types::*; +use crate::yui::auth::*; +use crate::yui::*; +use crate::Instances; +use rocket::serde::json::Json; +use rocket_db_pools::Connection; +use sea_orm::ActiveValue::{NotSet, Set}; +use sea_orm::{ + ActiveModelTrait, ColumnTrait, EntityTrait, ModelTrait, PaginatorTrait, QueryFilter, +}; + +/// Create a new instance +#[post("/instances", format = "application/json", data = "")] +pub async fn new_instance( + db: Connection, + iinfo: Json, + _api: APIUser, +) -> Result, APIError> { + let iinfo: InstanceReq = iinfo.into_inner(); + let ii_name = iinfo.name.clone(); + + // loosely validate ssh keys + if let Some(ssh_keys) = &iinfo.ssh_keys { + for (i, key) in ssh_keys.iter().enumerate() { + if key.contains('\n') { + return Err(api_err!( + BadRequest, + "SSH Key {} contains newlines. Ensure SSH keys are split as an array", + i + )); + } + } + } + + // validation: confirm hostname isn't in use + if instance_info::Entity::find() + .filter(instance_info::Column::Hostname.eq(ii_name)) + .count(&*db) + .await + .map_err(|e| api_err!(InternalServerError, "Database access failed: {:?}", e))? + != 0 + { + return Err(api_err!(BadRequest, "Hostname already exists")); + } + + // validation: confirm mac address isn't in use + let inst_mac = MacAddr::try_from(iinfo.mac_address) + .map_err(|_| api_err!(BadRequest, "MAC address is invalid"))?; + if instance_info::Entity::find() + .filter(instance_info::Column::MacAddress.eq(inst_mac.to_string())) + .count(&*db) + .await + .map_err(|e| api_err!(InternalServerError, "Database access failed: {:?}", e))? + != 0 + { + return Err(api_err!(Conflict, "MAC Address is in use")); + } + + // create and commit the instance info + let newid: u32 = (inst_mac[3] as u32) << 24 + | (inst_mac[4] as u32) << 16 + | (inst_mac[5] as u32) << 8 + | (rand::random::() as u32); + let iisql = instance_info::ActiveModel { + id: Set(newid), + hostname: Set(iinfo.name.clone()), + mac_address: Set(inst_mac.to_string()), + ssh_keys: match iinfo.ssh_keys { + Some(keys) => Set(Some(keys.join("\n"))), + None => NotSet, + }, + user_data: Set(iinfo + .user_data + .map(base64::decode) + .map_or(Ok(None), |v| v.map(Some)) + .map_err(|e| api_err!(BadRequest, "Error decoding user-data: {:?}", e))?), + }; + + match iisql.insert(&*db).await { + Ok(v) => Ok(Json(InstanceResponse::new(vec![v]))), + Err(err) => Err(api_err!( + InternalServerError, + "Failed to add record: {:?}", + err + )), + } +} + +/// List all instances in the database +#[get("/instances")] +pub async fn get_instances( + db: Connection, + _api: APIUser, +) -> Result, APIError> { + match instance_info::Entity::find().all(&*db).await { + Ok(v) => Ok(Json(InstanceResponse::new(v))), + Err(err) => Err(api_err!( + InternalServerError, + "Failed to get records: {:?}", + err + )), + } +} + +/// Get a specified instance +#[get("/instances/")] +pub async fn get_instance( + db: Connection, + id: u32, + _api: APIUser, +) -> Result, APIError> { + match instance_info::Entity::find_by_id(id) + .one(&*db) + .await + .map_err(|e| api_err!(InternalServerError, "Database error: {:?}", e))? + { + Some(v) => Ok(Json(InstanceResponse::new(vec![v]))), + None => Err(api_err!(NotFound, "Instance not found")), + } +} + +/// Delete an instance from the database +#[delete("/instances/")] +pub async fn delete_instance( + db: Connection, + id: u32, + _api: APIUser, +) -> Result<(), APIError> { + match instance_info::Entity::find_by_id(id) + .one(&*db) + .await + .map_err(|e| api_err!(InternalServerError, "Error deleting instance: {:?}", e))? + { + Some(ent) => { + ent.delete(&*db) + .await + .map_err(|e| api_err!(InternalServerError, "Error deleting instance: {:?}", e))?; + Ok(()) + } + None => Err(api_err!(NotFound, "Instance not found")), + } +} + +// Set a default (primarily, ssh-keys) +#[post("/config/", format = "plain", data = "")] +async fn set_defaults( + db: Connection, + key: String, + val: String, + _api: APIUser, +) -> Result<(), APIError> { + let key: DefaultKey = key + .try_into() + .map_err(|_| api_err!(BadRequest, "Invalid default key"))?; + match defaults::Entity::find_by_id(key) + .one(&*db) + .await + .map_err(|e| api_err!(InternalServerError, "Error getting default: {:?}", e))? + { + Some(def) => { + let mut model: defaults::ActiveModel = def.into(); + model.value = Set(val); + model.update(&*db).await.map(|_| ()) + } + None => { + let model = defaults::ActiveModel { + key: Set(key), + value: Set(val), + }; + model.insert(&*db).await.map(|_| ()) + } + } + .map_err(|e| api_err!(InternalServerError, "Error setting `{}`: {:?}", key, e)) +} + +// get a default setting +#[get("/config/")] +async fn get_defaults( + db: Connection, + key: String, + _api: APIUser, +) -> Result { + let key: DefaultKey = key + .try_into() + .map_err(|_| api_err!(BadRequest, "Invalid default key"))?; + defaults::Entity::find_by_id(key) + .one(&*db) + .await + .map_err(|e| api_err!(InternalServerError, "Error getting default: {:?}", e))? + .map_or(Err(api_err!(NotFound, "Key not yet set")), |v| Ok(v.value)) +} + +pub fn all() -> Vec { + routes![ + new_instance, + get_instances, + get_instance, + delete_instance, + set_defaults, + get_defaults, + ] +} diff --git a/src/yui/test.rs b/src/yui/test.rs new file mode 100644 index 0000000..3b7385a --- /dev/null +++ b/src/yui/test.rs @@ -0,0 +1,145 @@ +use super::routes::*; +use super::InstanceResponse; +use crate::rocket; +use crate::test::*; +use rocket::http::{ContentType, Header, Status}; +use rocket::local::blocking::Client; +use std::net::{Ipv6Addr, SocketAddr, SocketAddrV6}; + +#[test] +fn auth_works_properly() { + let client = Client::tracked(rocket()).expect("valid rocket instance"); + let api_header: Header = Header::new("x-api-key", SNAKEOIL_KEY); + + // wrong client IP - should return Forbidden + let response = client + .get(uri!("/_yui/", get_instances())) + .remote(SocketAddr::V6(SocketAddrV6::new(LLV6_IP, 8080, 0, 0))) + .dispatch(); + + assert_eq!(response.status(), Status::Forbidden); + + // no API key - should return Unauthorized + let response = client + .get(uri!("/_yui/", get_instances())) + .remote(saddr6!(localhost)) + .dispatch(); + + assert_eq!(response.status(), Status::Unauthorized); + + // API key, and localhost -- should be OK + let response = client + .get(uri!("/_yui/", get_instances())) + .remote(saddr6!(localhost)) + .header(api_header) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); +} + +#[test] +fn endpoints_require_auth() { + let client = Client::tracked(rocket()).expect("valid rocket instance"); + let test_instance = super::InstanceReq { + name: "test-pc".to_owned(), + mac_address: LLV6_MACSTR.to_owned(), + ssh_keys: None, + user_data: None, + }; + + let reqs = vec![ + client + .post(uri!("/_yui/", new_instance())) + .json(&test_instance), + client.get(uri!("/_yui/", get_instances())), + client.get(uri!("/_yui/", get_instance(0))), + client.delete(uri!("/_yui/", delete_instance(0))), + client.get(uri!("/_yui/", get_defaults("ssh_keys".to_owned()))), + client + .post(uri!("/_yui/", set_defaults("ssh_keys".to_owned()))) + .header(ContentType::Plain) + .body(SPEEX), + ]; + + for r in reqs { + let resp = r.remote(saddr6!(localhost)).dispatch(); + + assert_eq!(resp.status(), Status::Unauthorized); + } +} + +#[test] +fn crud() { + let client = Client::tracked(rocket()).expect("valid rocket instance"); + let test_instance = super::InstanceReq { + name: "test-pc".to_owned(), + mac_address: LLV6_MACSTR.to_owned(), + ssh_keys: None, + user_data: None, + }; + let api_header: Header = Header::new("x-api-key", SNAKEOIL_KEY); + + // Create the instance + let response = client + .post(uri!("/_yui/", new_instance())) + .json(&test_instance) + .remote(saddr6!(localhost)) + .header(api_header.clone()) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + let json_resp = response + .into_json::() + .expect("json in form InstanceResponse"); + + // make sure there's no error... + assert_eq!(json_resp.error, None); + // ... and that the Vec<> is available + let instances = json_resp.instances.expect("Some(Vec)"); + // ... and that it's not empty + assert_eq!(instances.len(), 1); + let saved = instances[0].clone(); + // ... and that the id is correct + let got_id = saved.id & 0xffffff00; + assert_eq!(got_id, 0x32a0fe00); + + // Try to get the instance + let response = client + .get(uri!("/_yui/", get_instance(saved.id))) + .remote(saddr6!(localhost)) + .header(api_header.clone()) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + let json_resp = response + .into_json::() + .expect("json in form InstanceResponse"); + let read_inst = json_resp.instances.unwrap()[0].clone(); + assert_eq!(read_inst, saved); + + // Delete instance + let response = client + .delete(uri!("/_yui/", delete_instance(saved.id))) + .remote(saddr6!(localhost)) + .header(api_header.clone()) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + + // Make sure it's deleted + let response = client + .get(uri!("/_yui/", get_instances())) + .remote(saddr6!(localhost)) + .header(api_header.clone()) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + let json_resp = response + .into_json::() + .expect("json in form InstanceResponse"); + + assert_eq!( + json_resp.instances.expect("empty Vec of instances").len(), + 0 + ); +}