From 41e80ca5089457858c303335915c16a73a58eeb7 Mon Sep 17 00:00:00 2001 From: znpra Date: Mon, 14 Aug 2023 17:00:42 -0400 Subject: [PATCH] users can set their authentication through a TSaR bot now! Can't be used for anything yet, though --- .gitignore | 4 + ...94fcb98c3a76db228002b01a93e74a747c44a.json | 20 - Cargo.lock | 521 +++++++++++++++++- Cargo.toml | 9 +- migrations/0002_basic_authentication.sql | 11 + src/main.rs | 21 +- src/tsar.rs | 300 ++++++++++ 7 files changed, 837 insertions(+), 49 deletions(-) delete mode 100644 .sqlx/query-a49c11570aff702c2e583a7e37a94fcb98c3a76db228002b01a93e74a747c44a.json create mode 100644 migrations/0002_basic_authentication.sql create mode 100644 src/tsar.rs diff --git a/.gitignore b/.gitignore index 4c8088d..9c003d5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ /target ttc_test* +eid + +# DO NOT COMMIT, CONTAINS SENSITIVE INFORMATION +login diff --git a/.sqlx/query-a49c11570aff702c2e583a7e37a94fcb98c3a76db228002b01a93e74a747c44a.json b/.sqlx/query-a49c11570aff702c2e583a7e37a94fcb98c3a76db228002b01a93e74a747c44a.json deleted file mode 100644 index fb3f82b..0000000 --- a/.sqlx/query-a49c11570aff702c2e583a7e37a94fcb98c3a76db228002b01a93e74a747c44a.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT pronouns \n FROM pronouns \n WHERE username == ?", - "describe": { - "columns": [ - { - "name": "pronouns", - "ordinal": 0, - "type_info": "Text" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false - ] - }, - "hash": "a49c11570aff702c2e583a7e37a94fcb98c3a76db228002b01a93e74a747c44a" -} diff --git a/Cargo.lock b/Cargo.lock index 5eb7b87..881df86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,6 +35,21 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[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 = "async-trait" version = "0.1.70" @@ -43,7 +58,7 @@ checksum = "79fa67157abdfd688a259b6648808757db9347af834624f27ec646da976aee5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.28", ] [[package]] @@ -55,6 +70,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -120,7 +146,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.28", ] [[package]] @@ -174,6 +200,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bumpalo" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + [[package]] name = "byteorder" version = "1.4.3" @@ -198,12 +230,42 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "winapi", +] + [[package]] name = "const-oid" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + [[package]] name = "cpufeatures" version = "0.2.9" @@ -295,6 +357,15 @@ dependencies = [ "serde", ] +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -363,6 +434,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.0" @@ -471,6 +557,31 @@ version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +[[package]] +name = "h2" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 1.9.3", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.0" @@ -487,7 +598,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f" dependencies = [ - "hashbrown", + "hashbrown 0.14.0", ] [[package]] @@ -499,6 +610,15 @@ 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 = "hermit-abi" version = "0.3.1" @@ -582,6 +702,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", + "h2", "http", "http-body", "httparse", @@ -595,6 +716,42 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "idna" version = "0.4.0" @@ -605,6 +762,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + [[package]] name = "indexmap" version = "2.0.0" @@ -612,9 +779,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.0", ] +[[package]] +name = "ipnet" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" + [[package]] name = "itertools" version = "0.10.5" @@ -630,6 +803,15 @@ version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -680,9 +862,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "matchit" @@ -737,6 +919,24 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "nom" version = "7.1.3" @@ -801,7 +1001,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.1", "libc", ] @@ -820,6 +1020,50 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "openssl" +version = "0.10.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -881,7 +1125,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.28", ] [[package]] @@ -986,6 +1230,43 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "reqwest" +version = "0.11.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + [[package]] name = "rsa" version = "0.9.2" @@ -1039,37 +1320,69 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" +[[package]] +name = "schannel" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +dependencies = [ + "windows-sys", +] + [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "serde" -version = "1.0.166" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d01b7404f9d441d3ad40e6a636a7782c377d2abdbe4fa2440e2edcc2f4f10db8" +checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.166" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd83d6dde2b6b2d466e14d9d1acce8816dedee94f735eac6395808b3483c6d6" +checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.28", ] [[package]] name = "serde_json" -version = "1.0.100" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f1e14e89be7aa4c4b78bdbdc9eb5bf8517829a600ae8eaa39a6e1d960b5185c" +checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" dependencies = [ "itoa", "ryu", @@ -1235,7 +1548,7 @@ dependencies = [ "futures-util", "hashlink", "hex", - "indexmap", + "indexmap 2.0.0", "log", "memchr", "once_cell", @@ -1394,6 +1707,19 @@ dependencies = [ "url", ] +[[package]] +name = "stderrlog" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69a26bbf6de627d389164afa9783739b56746c6c72c4ed16539f4ff54170327b" +dependencies = [ + "atty", + "chrono", + "log", + "termcolor", + "thread_local", +] + [[package]] name = "stringprep" version = "0.1.3" @@ -1423,9 +1749,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.23" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ "proc-macro2", "quote", @@ -1451,6 +1777,15 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.44" @@ -1468,7 +1803,17 @@ checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.28", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", ] [[package]] @@ -1514,7 +1859,17 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.28", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", ] [[package]] @@ -1528,6 +1883,20 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-util" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + [[package]] name = "tower" version = "0.4.13" @@ -1577,7 +1946,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.28", ] [[package]] @@ -1600,8 +1969,15 @@ name = "ttc_backend" version = "0.1.0" dependencies = [ "axum", + "base64", + "log", "rand", + "reqwest", + "serde", + "serde_json", + "sha2", "sqlx", + "stderrlog", "tokio", ] @@ -1682,6 +2058,82 @@ 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.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.28", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "whoami" version = "1.4.1" @@ -1704,12 +2156,30 @@ 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.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -1776,6 +2246,15 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + [[package]] name = "zeroize" version = "1.6.0" diff --git a/Cargo.toml b/Cargo.toml index 8bc851f..89110ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,14 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -axum ={ version = "0.6.18", features = ["macros"] } +axum = { version = "0.6.18", features = ["macros"] } tokio = { version = "1.29.1", features = ["full"] } rand = { version = "0.8.5", features = ["std"] } sqlx = { version = "0.7.1", features = ["runtime-tokio", "sqlite"] } +serde_json = "1.0.104" +reqwest = { version = "0.11.18", features = ["json"] } +serde = { version = "1.0.183", features = ["serde_derive"] } +stderrlog = "0.5.4" +log = "0.4.20" +base64 = "0.21.2" +sha2 = "0.10.7" diff --git a/migrations/0002_basic_authentication.sql b/migrations/0002_basic_authentication.sql new file mode 100644 index 0000000..4ef5c71 --- /dev/null +++ b/migrations/0002_basic_authentication.sql @@ -0,0 +1,11 @@ +-- allow pronouns to be null +ALTER TABLE pronouns ADD COLUMN pronouns_nullable_tmp TEXT; +UPDATE pronouns SET pronouns_nullable_tmp = pronouns; +ALTER TABLE pronouns DROP COLUMN pronouns; +ALTER TABLE pronouns RENAME COLUMN pronouns_nullable_tmp TO pronouns; + +-- change table name +ALTER TABLE pronouns RENAME TO users; + +-- add authentication field +ALTER TABLE users ADD COLUMN auth BLOB; diff --git a/src/main.rs b/src/main.rs index d7335c7..344e7b4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +mod tsar; + use std::{env, net::{IpAddr, SocketAddr}}; use axum::{ @@ -12,15 +14,19 @@ use sqlx::{SqlitePool, sqlite::SqlitePoolOptions}; #[tokio::main] async fn main() { let port = env::var("TTC_PORT").unwrap_or("9000".into()).parse().unwrap(); - let pool = SqlitePoolOptions::new() + let pool: &SqlitePool = Box::leak(Box::new( + SqlitePoolOptions::new() .max_connections(5) .connect(env::var("TTC_DATABASE_URL") .unwrap_or("sqlite:ttc.db".into()) .as_ref()) .await - .unwrap(); + .unwrap() + )); + + sqlx::migrate!("./migrations").run(pool).await.unwrap(); - sqlx::migrate!("./migrations").run(&pool).await.unwrap(); + tokio::task::spawn(tsar::run_tsar(pool)); let app = Router::new() .route("/api/thethirdcan/hello", get(|| async { "hello world!" })) @@ -35,22 +41,23 @@ async fn main() { async fn user_pronouns( - State(pool): State, + State(pool): State<&SqlitePool>, Path(user): Path, ) -> Result { sqlx::query!("SELECT pronouns - FROM pronouns + FROM users WHERE username == ?", user) - .fetch_one(&pool) + .fetch_one(pool) .await .map_err(|err| match err { sqlx::Error::RowNotFound => StatusCode::NOT_FOUND, _ => StatusCode::INTERNAL_SERVER_ERROR })? .pronouns + .ok_or(StatusCode::NOT_FOUND)? .split(';') .choose(&mut thread_rng()) .map(ToOwned::to_owned) - .ok_or(StatusCode::NOT_FOUND) + .ok_or(StatusCode::INTERNAL_SERVER_ERROR) } diff --git a/src/tsar.rs b/src/tsar.rs new file mode 100644 index 0000000..9d0ccf8 --- /dev/null +++ b/src/tsar.rs @@ -0,0 +1,300 @@ +use std::{error::Error, fs::File, time::Duration, io::{Read, Write}, cmp::max}; +use log::*; +use rand::{thread_rng, Rng}; +use base64::prelude::*; + +use reqwest::Client; +use serde::{Serialize, Deserialize}; +use sha2::{Sha256, Digest}; +use sqlx::SqlitePool; + +#[derive(Serialize, Deserialize, Debug)] +struct LoginInfo { + #[serde(rename = "user")] + username: String, + auth: String, + uid: i64, +} + +#[derive(Serialize, Debug)] +#[serde(tag = "fn")] +enum StitchFunction { + #[serde(rename = "banter.list")] + GetMessages { + folder: String, + start: i64, + results: i64, + }, + + #[serde(rename = "chat.action")] + SendMessage { + sid: i64, + text: String, + action: String, // should ALWAYS be "SENDSESS" + } +} + +#[derive(Serialize, Debug)] +struct StitchCall { + username: String, + auth: String, + #[serde(rename = "expectUserChange")] + expect_user_change: bool, + #[serde(rename = "requests")] + functions: Vec, +} + +#[derive(Deserialize, Debug)] +struct MessageMemberDescription { + #[serde(default)] + uid: Option, + #[serde(default)] + you: bool, + mid: i64, + #[serde(rename = "readThru")] + last_eid_read: i64, +} + +#[derive(Deserialize, Debug)] +struct MessageEvent { + eid: i64, + mid: i64, + time: i64, + #[serde(rename = "type")] + event_type: String, + data: String, +} + +#[derive(Deserialize, Debug)] +struct MessageThreadDescription { + sid: i64, + title: String, + preview: String, + uids: Vec, + #[serde(rename = "areYouAnon")] + are_you_anon: bool, + #[serde(rename = "lastEid")] + last_eid: i64, + #[serde(rename = "type")] + thread_type: String, + members: Vec, + events: Vec, + #[serde(rename = "readToEid", default)] + read_to_eid: i64, + #[serde(rename = "groupId", default)] + group_id: Option, +} + +#[derive(Deserialize, Debug)] +#[serde(untagged)] +enum StitchFunctionResponse { + GetMessages { + folder: String, + items: Vec, + #[serde(rename = "endReached")] + end_reached: bool, + ok: bool, + tag: String, + }, +} + +#[derive(Deserialize, Debug)] +struct UserDescription { + id: i64, + name: String, + key: String, + seen: i64, + #[serde(rename = "avatarId")] + avatar_id: i64, + #[serde(rename = "avatar")] + avatar_path: String, + #[serde(rename = "posts")] + post_count: i64, +} + +#[derive(Deserialize, Debug)] +struct StitchResponse { + ok: bool, + responses: Vec, + users: Vec, + auth: String, + v: String, +} + +impl StitchCall { + fn from_login_info(login_info: &LoginInfo, expect_user_change: bool, functions: Vec) -> Self { + Self { + username: login_info.username.clone(), + auth: login_info.auth.clone(), + expect_user_change, + functions + } + } +} + +impl StitchFunction { + fn send_message(sid: i64, text: String) -> Self { + Self::SendMessage { + sid, + text, + action: "SENDSESS".into() + } + } +} + + +async fn send_message(client: &Client, login: &LoginInfo, sid: i64, text: String) -> Result<(), ()> { + let call = StitchCall::from_login_info(login, false, vec![StitchFunction::send_message(sid, text)]); + client.post("https://twocansandstring.com/stitchservices") + .json(&call) + .send() + .await + .map(|_| ()) + .map_err(|e| error!("Failed to send message witht error {}", e)) +} + + +async fn handle_event(pool: &SqlitePool, login: &LoginInfo, thread: &MessageThreadDescription, res: &StitchResponse, client: &Client) -> Result<(), ()> { + let event = &thread.events[0]; + let text = event.data.split_at(2).1.to_lowercase(); + let sid = thread.sid; + let mid = event.mid; + let Some(uid) = thread.members.iter().find(|member| member.mid == mid).and_then(|member| member.uid) else { return Err(()) }; + let Some(username) = res.users.iter().find(|user| user.id == uid).map(|user| &user.name) else { return Err(()) }; + + debug!("handling '{text}' from {username} in thread {sid}"); + + if text.starts_with("help") { + send_message(client, login, sid, +r#"To generate a new authentication code, send a message with the text "get_authentication" (without quotes). +Note: this will remove your previous authentication code, if you had one."#.into() + ).await?; + } else if text.starts_with("get_authentication") { + let key_data: [u8; 16] = thread_rng().gen(); + let b64_key = BASE64_URL_SAFE.encode(key_data); + let hashed_key = { + let mut hasher = Sha256::new(); + hasher.update(key_data); + hasher.update("get salted on lmao"); + hasher.finalize() + }; + let hashed_key_slice = hashed_key.as_slice(); + + + let user_in_db = sqlx::query!("SELECT username FROM users WHERE username == ?;", username) + .fetch_optional(pool) + .await + .map_err(|e| error!("failed to search database for username: {e}"))? + .is_some(); + + if user_in_db { + sqlx::query!("UPDATE users + SET auth = ? + WHERE username == ?; + ", hashed_key_slice, username) + .execute(pool) + .await + .map_err(|e| error!("failed to update authentication key: {e}"))?; + } else { + sqlx::query!("INSERT INTO users (username, auth) + VALUES (?, ?); + ", username, hashed_key_slice) + .execute(pool) + .await + .map_err(|e| error!("failed to create user for authentication: {e}"))?; + } + + send_message(client, login, sid, +format!("A new authentication code has been generated. If you had a previous code, it is now invalid. +!!! NOTE: THIS IS A PASSWORD; DO NOT SHARE IT WITH OTHERS !!! +Your authentication code is displayed below: + +{b64_key} +") + ).await?; + send_message(client, login, sid, +"In order to use this code for The Third Can, open the extension popup and navigate to the authentication section. It will have a text box where you can enter your code.".into() + ).await?; + } + + Ok(()) +} + + +async fn poll_tsar(pool: &SqlitePool, client: &Client, messages_request_body: &StitchCall, last_eid_handled: &mut i64, login: &LoginInfo) -> Result<(), Box> { + println!("Querying messages"); + let recent_messages = client.post("https://twocansandstring.com/stitchservices") + .json(&messages_request_body) + .send() + .await? + .text() + .await?; + let mut res: StitchResponse = serde_json::from_str(&recent_messages)?; + let threads = match res.responses.pop().unwrap() { + StitchFunctionResponse::GetMessages { items, .. } => items, + }; + + let mut new_last_eid_handled = 0i64; + for thread in threads.into_iter() + .filter(|thread| thread.last_eid > *last_eid_handled) + .filter(|thread| { + thread.members.iter() + .find(|m| m.you) + .is_some_and(|you| thread.events[0].mid != you.mid) + }) + { + let success = handle_event(pool, &login, &thread, &res, &client).await; + + if success.is_ok() { + new_last_eid_handled = max(thread.events[0].eid, new_last_eid_handled); + } + } + + *last_eid_handled = max(*last_eid_handled, new_last_eid_handled); + { + let mut eid_file = File::create("eid")?; + eid_file.write_all(&last_eid_handled.to_le_bytes())?; + } + + Ok(()) +} + + +pub async fn run_tsar(pool: &SqlitePool) { + println!("Initializing TSaR"); + + let login_info: LoginInfo = { + let login_file = File::open("login").expect("login file must exist"); + serde_json::from_reader(login_file).expect("login file must be readable") + }; + + let mut last_eid_handled: i64 = { + let mut out = [0u8;8]; + File::open("eid") + .ok() + .and_then(|mut file| file.read(&mut out).ok()); + i64::from_le_bytes(out) + }; + + + let client = Client::new(); + let request_period = Duration::from_secs(10); + let messages_request_body = StitchCall::from_login_info( + &login_info, + false, + vec![StitchFunction::GetMessages { + folder: "inbox".into(), + start: 0, + results: 20, + }] + ); + + + loop { + poll_tsar(pool, &client, &messages_request_body, &mut last_eid_handled, &login_info) + .await + .unwrap_or_else( |err| error!("{}", err.to_string()) ); + + tokio::time::sleep(request_period).await; + } +}