From 7f4efb812232f9c70292b013bbf44ef62082f47f Mon Sep 17 00:00:00 2001 From: jeff Date: Tue, 29 Dec 2020 23:06:41 +0000 Subject: [PATCH] Rip out Diesel in favor of SQLx. The primary benefit of this is to avoid Rocket's database integration, which has become problematic in this codebase with the update to the new async style. Because the async database API is actually synchronous under the hood, this introduces some annoying lifetime requirements that basically force us to use owned data everywhere. The original pattern was to have a separate data layer that could invoke queries from `self` (the db connection). By using a true async database driver, we can get this back, because the lifetimes are once again flexible instead of the ones forced by Rocket. --- Cargo.lock | 606 ++++++++++++++++++++++++++++++---- Cargo.toml | 5 +- src/db.rs | 175 +++++----- src/errors.rs | 9 +- src/main.rs | 10 +- src/models/characters.rs | 17 +- src/models/users.rs | 14 +- src/routes/api.rs | 10 +- src/routes/auth.rs | 21 +- src/routes/characters.rs | 4 +- src/routes/characters/edit.rs | 4 +- src/routes/characters/new.rs | 8 +- src/routes/root.rs | 2 +- src/schema.rs | 30 -- 14 files changed, 673 insertions(+), 242 deletions(-) delete mode 100644 src/schema.rs diff --git a/Cargo.lock b/Cargo.lock index 61eb6a2..43ff2c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,6 +54,23 @@ dependencies = [ "opaque-debug 0.3.0", ] +[[package]] +name = "ahash" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" + +[[package]] +name = "ahash" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75b7e6a93ecd6dbd2c225154d0fa7f86205574ecaa6c87429fb5f66ee677c44" +dependencies = [ + "getrandom 0.2.0", + "lazy_static", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.15" @@ -92,6 +109,15 @@ dependencies = [ "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 = "atomic" version = "0.5.0" @@ -142,6 +168,18 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "bitvec" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7ba35e9565969edb811639dbebfe34edc0368e472c5018474c8eb2543397f81" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "blake2b_simd" version = "0.5.11" @@ -201,6 +239,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "build_const" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" + [[package]] name = "bumpalo" version = "3.4.0" @@ -225,6 +269,24 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" +[[package]] +name = "cargo_metadata" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83f95cf4bf0dda0ac2e65371ae7215d0dce3c187613a9dbf23aaa9374186f97a" +dependencies = [ + "semver 0.11.0", + "semver-parser 0.10.0", + "serde", + "serde_json", +] + +[[package]] +name = "cc" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" + [[package]] name = "cfg-if" version = "0.1.10" @@ -297,6 +359,22 @@ dependencies = [ "version_check", ] +[[package]] +name = "core-foundation" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" + [[package]] name = "cpuid-bool" version = "0.1.2" @@ -309,6 +387,35 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" +[[package]] +name = "crc" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" +dependencies = [ + "build_const", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f6cb3c7f5b8e51bc3ebb73a2327ad4abdbd119dc13223f14f961d2f38486756" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.1" @@ -366,41 +473,6 @@ dependencies = [ "syn", ] -[[package]] -name = "diesel" -version = "1.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2de9deab977a153492a1468d1b1c0662c1cf39e5ea87d0c060ecd59ef18d8c" -dependencies = [ - "byteorder", - "diesel_derives", - "libsqlite3-sys", - "r2d2", -] - -[[package]] -name = "diesel-derive-enum" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703e71c268ea2d8da9c0ab0b40d8b217179ee622209c170875d24443193a0dfb" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "diesel_derives" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "digest" version = "0.8.1" @@ -425,6 +497,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + [[package]] name = "either" version = "1.6.1" @@ -483,6 +561,31 @@ 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.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00" +dependencies = [ + "matches", + "percent-encoding", +] + [[package]] name = "fsevent" version = "0.4.0" @@ -518,6 +621,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +[[package]] +name = "funty" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + [[package]] name = "futures" version = "0.3.8" @@ -643,6 +752,17 @@ dependencies = [ "wasi 0.9.0+wasi-snapshot-preview1", ] +[[package]] +name = "getrandom" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8025cf36f917e6a52cce185b7c7177689b838b7ec138364e50cc2277a56cf4" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "ghash" version = "0.3.0" @@ -707,6 +827,18 @@ name = "hashbrown" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +dependencies = [ + "ahash 0.4.7", +] + +[[package]] +name = "hashlink" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d99cf782f0dc4372d26846bec3de7804ceb5df083c2d4462c0b8d2330e894fa8" +dependencies = [ + "hashbrown", +] [[package]] name = "heck" @@ -726,6 +858,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hex" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" + [[package]] name = "hkdf" version = "0.9.0" @@ -809,6 +947,17 @@ dependencies = [ "want", ] +[[package]] +name = "idna" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "ignore" version = "0.4.17" @@ -896,6 +1045,15 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" +[[package]] +name = "js-sys" +version = "0.3.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d7383929f7c9c7c2d0fa596f325832df98c3704f2c60553080f7127a58175" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -918,6 +1076,19 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "lexical-core" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616" +dependencies = [ + "arrayvec", + "bitflags", + "cfg-if 0.1.10", + "ryu", + "static_assertions", +] + [[package]] name = "libc" version = "0.2.80" @@ -926,10 +1097,11 @@ checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" [[package]] name = "libsqlite3-sys" -version = "0.18.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e704a02bcaecd4a08b93a23f6be59d0bd79cd161e0963e9499165a0a35df7bd" +checksum = "64d31059f22935e6c31830db5249ba2b7ecd54fd73a9909286f0a67aa55c2fbd" dependencies = [ + "cc", "pkg-config", "vcpkg", ] @@ -958,6 +1130,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" + [[package]] name = "memchr" version = "2.3.4" @@ -1030,6 +1208,24 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1255076139a83bb467426e7f8d0134968a8118844faa755985e077cf31850333" +[[package]] +name = "native-tls" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fcc7939b5edc4e4f86b1b4a04bb1498afaaf871b1a6691838ed06fcb48d3a3f" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "net2" version = "0.2.36" @@ -1041,6 +1237,18 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "nom" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88034cfd6b4a0d54dd14f4a507eceee36c0b70e5a02236c4e4df571102be17f0" +dependencies = [ + "bitvec", + "lexical-core", + "memchr", + "version_check", +] + [[package]] name = "notify" version = "4.0.15" @@ -1106,6 +1314,39 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "openssl" +version = "0.10.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038d43985d1ddca7a9900630d8cd031b56e4794eecc2e9ea39dd17aa04399a70" +dependencies = [ + "bitflags", + "cfg-if 1.0.0", + "foreign-types", + "lazy_static", + "libc", + "openssl-sys", +] + +[[package]] +name = "openssl-probe" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" + +[[package]] +name = "openssl-sys" +version = "0.9.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "921fc71883267538946025deffb622905ecad223c28efbfdef9bb59a0175f3e6" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "parking_lot" version = "0.11.1" @@ -1398,15 +1639,10 @@ dependencies = [ ] [[package]] -name = "r2d2" -version = "0.8.9" +name = "radium" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545c5bc2b880973c9c10e4067418407a0ccaa3091781d1671d46eb35107cb26f" -dependencies = [ - "log", - "parking_lot", - "scheduled-thread-pool", -] +checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" [[package]] name = "rand" @@ -1414,7 +1650,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom", + "getrandom 0.1.15", "libc", "rand_chacha", "rand_core", @@ -1437,7 +1673,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom", + "getrandom 0.1.15", ] [[package]] @@ -1548,26 +1784,13 @@ name = "rocket_contrib" version = "0.5.0-dev" source = "git+https://github.com/SergioBenitez/Rocket#1f1f44f336e5a172361fc1860461bb03667b1ed2" dependencies = [ - "diesel", "glob", "log", "notify", - "r2d2", "rocket", - "rocket_contrib_codegen", "serde", "serde_json", "tera", - "tokio", -] - -[[package]] -name = "rocket_contrib_codegen" -version = "0.5.0-dev" -source = "git+https://github.com/SergioBenitez/Rocket#1f1f44f336e5a172361fc1860461bb03667b1ed2" -dependencies = [ - "devise", - "quote", ] [[package]] @@ -1613,7 +1836,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver", + "semver 0.9.0", ] [[package]] @@ -1632,12 +1855,13 @@ dependencies = [ ] [[package]] -name = "scheduled-thread-pool" -version = "0.2.5" +name = "schannel" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6f74fd1204073fa02d5d5d68bec8021be4c38690b61264b2fdb48083d0e7d7" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" dependencies = [ - "parking_lot", + "lazy_static", + "winapi 0.3.9", ] [[package]] @@ -1646,13 +1870,46 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "security-framework" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1759c2e3c8580017a484a7ac56d3abc5a6c1feadf88db2f3633f12ae4268c69" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f99b9d5e26d2a71633cc4f2ebae7cc9f874044e0c351a27e17892d76dce5678b" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "semver-parser", + "semver-parser 0.7.0", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser 0.10.0", + "serde", ] [[package]] @@ -1661,6 +1918,16 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "semver-parser" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e012c6c5380fb91897ba7b9261a0f565e624e869d42fe1a1d03fa0d68a083d5" +dependencies = [ + "pest", + "pest_derive", +] + [[package]] name = "serde" version = "1.0.117" @@ -1765,6 +2032,101 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "sqlformat" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74c70f0235b9925cbb106c52af1a28b5ea4885a8b851e328b8562e257a389c2d" +dependencies = [ + "lazy_static", + "maplit", + "nom", + "regex", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1a98f9bf17b690f026b6fec565293a995b46dfbd6293debcb654dcffd2d1b34" +dependencies = [ + "sqlx-core", + "sqlx-macros", +] + +[[package]] +name = "sqlx-core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36bb6a2ca3345a86493bc3b71eabc2c6c16a8bb1aa476cf5303bee27f67627d7" +dependencies = [ + "ahash 0.6.2", + "atoi", + "bitflags", + "byteorder", + "bytes", + "crc", + "crossbeam-channel", + "crossbeam-queue", + "crossbeam-utils", + "either", + "futures-channel", + "futures-core", + "futures-util", + "hashlink", + "hex", + "itoa", + "libc", + "libsqlite3-sys", + "log", + "memchr", + "once_cell", + "parking_lot", + "percent-encoding", + "sha2", + "smallvec", + "sqlformat", + "sqlx-rt", + "stringprep", + "thiserror", + "url", + "whoami", +] + +[[package]] +name = "sqlx-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5ada8b3b565331275ce913368565a273a74faf2a34da58c4dc010ce3286844" +dependencies = [ + "cargo_metadata", + "dotenv", + "either", + "futures", + "heck", + "lazy_static", + "proc-macro2", + "quote", + "sha2", + "sqlx-core", + "sqlx-rt", + "syn", + "url", +] + +[[package]] +name = "sqlx-rt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63fc5454c9dd7aaea3a0eeeb65ca40d06d0d8e7413a8184f7c3a3ffa5056190b" +dependencies = [ + "native-tls", + "once_cell", + "tokio", + "tokio-native-tls", +] + [[package]] name = "standback" version = "0.2.13" @@ -1780,6 +2142,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "stdweb" version = "0.4.20" @@ -1829,6 +2197,16 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" +[[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 = "strum" version = "0.20.0" @@ -1867,6 +2245,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "tap" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36474e732d1affd3a6ed582781b3683df3d0563714c59c39591e8ff707cf078e" + [[package]] name = "tempfile" version = "3.1.0" @@ -1885,8 +2269,6 @@ dependencies = [ name = "tenebrous-sheets" version = "0.1.0" dependencies = [ - "diesel", - "diesel-derive-enum", "erased-serde", "futures", "log", @@ -1899,6 +2281,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", + "sqlx", "strum", "thiserror", ] @@ -2003,6 +2386,21 @@ dependencies = [ "syn", ] +[[package]] +name = "tinyvec" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf8dbc19eb42fba10e8feaaec282fb50e2c14b2726d6301dbfeed0f73306a6f" +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 = "0.2.24" @@ -2037,6 +2435,16 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-native-tls" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd608593a919a8e05a7d1fc6df885e40f6a88d3a70a3a7eff23ff27964eda069" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-util" version = "0.3.1" @@ -2183,6 +2591,24 @@ dependencies = [ "unic-common", ] +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +dependencies = [ + "matches", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13e63ab62dbe32aeee58d1c5408d35c36c392bba5d9d3142287219721afe606" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-segmentation" version = "1.7.1" @@ -2195,6 +2621,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +[[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.0" @@ -2205,6 +2637,18 @@ dependencies = [ "subtle", ] +[[package]] +name = "url" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding", +] + [[package]] name = "vcpkg" version = "0.2.10" @@ -2304,6 +2748,16 @@ version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158" +[[package]] +name = "web-sys" +version = "0.3.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222b1ef9334f92a21d3fb53dc3fd80f30836959a90f9274a626d7e06315ba3c3" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "which" version = "3.1.1" @@ -2313,6 +2767,16 @@ dependencies = [ "libc", ] +[[package]] +name = "whoami" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35495e7faf4c657051a8e9725d9c37ac57879e915be3ed55bb401af84382035" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + [[package]] name = "winapi" version = "0.2.8" @@ -2366,6 +2830,12 @@ dependencies = [ "winapi-build", ] +[[package]] +name = "wyz" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + [[package]] name = "yansi" version = "0.5.0" diff --git a/Cargo.toml b/Cargo.toml index 16babc0..c60e66e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,14 +14,13 @@ serde = "1.0" serde_derive = "1.0" serde_json = "1.0" erased-serde = "0.3" -diesel = "1.4" -diesel-derive-enum = { version = "1", features = ["sqlite"] } thiserror = "1.0" rust-argon2 = "0.8" log = "0.4" rand = "0.7" futures = "0.3" strum = { version = "0.20", features = ["derive"] } +sqlx = { version = "0.4.2", features = [ "sqlite", "runtime-tokio-native-tls" ] } [dependencies.rocket] git = "https://github.com/SergioBenitez/Rocket" @@ -32,4 +31,4 @@ features = ["secrets"] git = "https://github.com/SergioBenitez/Rocket" branch = "master" default-features = false -features = [ "tera_templates", "diesel_sqlite_pool", "serve" ] \ No newline at end of file +features = [ "tera_templates", "serve" ] \ No newline at end of file diff --git a/src/db.rs b/src/db.rs index 069573f..b5365c0 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,120 +1,119 @@ -use crate::models::characters::{Character, NewCharacter, StrippedCharacter}; +use crate::errors::Error; +use crate::models::characters::{Character, CharacterDataType, NewCharacter, StrippedCharacter}; use crate::models::users::{NewUser, User}; -use crate::schema::characters; -use diesel::prelude::*; -use rocket_contrib::databases::diesel; +use sqlx::database::HasValueRef; +use sqlx::sqlite::{SqlitePool, SqlitePoolOptions}; +use sqlx::Decode; -#[database("tenebrous_db")] -pub(crate) struct TenebrousDbConn(SqliteConnection); +pub type TenebrousDbConn<'a> = rocket::State<'a, SqlitePool>; + +pub(crate) async fn create_pool() -> Result { + SqlitePoolOptions::new() + .max_connections(5) + .connect("tenebrous.sqlite") + .await + .map_err(|e| e.into()) +} #[rocket::async_trait] pub(crate) trait Dao { - async fn load_user_by_id(&self, id: i32) -> QueryResult>; + async fn load_user_by_id(&self, id: i32) -> Result, Error>; - async fn load_user(&self, for_username: String) -> QueryResult>; + async fn load_user(&self, for_username: &str) -> Result, Error>; - async fn insert_user(&self, new_user: NewUser) -> QueryResult; + async fn insert_user(&self, new_user: NewUser<'_>) -> Result; - async fn load_character_list(&self, for_user_id: i32) -> QueryResult>; + async fn load_character_list(&self, for_user_id: i32) -> Result, Error>; - async fn load_character(&self, character_id: i32) -> QueryResult>; + async fn load_character(&self, character_id: i32) -> Result, Error>; - async fn insert_character(&self, new_character: NewCharacter) -> QueryResult<()>; + async fn insert_character(&self, new_character: NewCharacter<'_>) -> Result<(), Error>; - async fn update_character_sheet(&self, character: Character) -> QueryResult<()>; + async fn update_character_sheet<'a>(&self, character: &'a Character) -> Result<(), Error>; } -type StrippedCharacterColumns = ( - characters::id, - characters::user_id, - characters::viewable, - characters::character_name, - characters::data_type, - characters::data_version, -); - -const STRIPPED_CHARACTER_COLUMNS: StrippedCharacterColumns = ( - characters::id, - characters::user_id, - characters::viewable, - characters::character_name, - characters::data_type, - characters::data_version, -); - +//TODO is: +// - reimplement all methods +// - remove owned data +// - return sqlx result so we don't have .into() calls everywhere +// - use compile time queries +// - find replacement for diesel migrations #[rocket::async_trait] -impl Dao for TenebrousDbConn { - async fn load_user_by_id(&self, user_id: i32) -> QueryResult> { - use crate::schema::users::dsl::*; - self.run(move |conn| users.filter(id.eq(user_id)).first(conn).optional()) +impl Dao for SqlitePool { + async fn load_user_by_id(&self, user_id: i32) -> Result, Error> { + sqlx::query_as::<_, User>("SELECT * FROM users WHERE id = ?") + .bind(user_id) + .fetch_optional(self) .await + .map_err(|e| e.into()) } - async fn load_user(&self, for_username: String) -> QueryResult> { - use crate::schema::users::dsl::*; + async fn load_user(&self, for_username: &str) -> Result, Error> { + sqlx::query_as::<_, User>("SELECT * FROM users WHERE username = ?") + .bind(for_username) + .fetch_optional(self) + .await + .map_err(|e| e.into()) + } - self.run(move |conn| { - users - .filter(username.eq(for_username)) - .first(conn) - .optional() - }) + async fn insert_user(&self, new_user: NewUser<'_>) -> Result { + sqlx::query("INSERT INTO users (username, password) values (?, ?)") + .bind(new_user.username) + .bind(new_user.password) + .execute(self) + .await?; + + self.load_user(new_user.username) + .await + .and_then(|user| user.ok_or(Error::NotFound)) + } + + async fn load_character_list(&self, for_user_id: i32) -> Result, Error> { + sqlx::query_as::<_, StrippedCharacter>( + "SELECT id, user_id, viewable, character_name, data_type, data_version + FROM characters WHERE user_id = ?", + ) + .bind(for_user_id) + .fetch_all(self) .await + .map_err(|e| e.into()) } - async fn insert_user(&self, new_user: NewUser) -> QueryResult { - self.run(move |conn| { - diesel::insert_into(users).values(&new_user).execute(conn)?; - - use crate::schema::users::dsl::*; - users.filter(username.eq(new_user.username)).first(conn) - }) + async fn load_character(&self, character_id: i32) -> Result, Error> { + sqlx::query_as::<_, Character>( + "SELECT id, user_id, viewable, character_name, data_type, data_version, data + FROM characters WHERE id = ?", + ) + .bind(character_id) + .fetch_optional(self) .await + .map_err(|e| e.into()) } - async fn load_character_list(&self, for_user_id: i32) -> QueryResult> { - use crate::schema::characters::dsl::*; - - self.run(move |conn| { - characters - .filter(user_id.eq(for_user_id)) - .select(STRIPPED_CHARACTER_COLUMNS) - .load(conn) - }) - .await - } - - async fn load_character(&self, character_id: i32) -> QueryResult> { - use crate::schema::characters::dsl::*; - - self.run(move |conn| { - characters - .filter(id.eq(character_id)) - .first(conn) - .optional() - }) - .await - } - - async fn insert_character(&self, new_character: NewCharacter) -> QueryResult<()> { - self.run(|conn| { - diesel::insert_into(characters::table) - .values(new_character) - .execute(conn) - }) + async fn insert_character(&self, new_character: NewCharacter<'_>) -> Result<(), Error> { + sqlx::query( + "INSERT INTO characters + (user_id, viewable, character_name, data_type, data_version, data) + values (?, ?, ?, ?, ?, ?)", + ) + .bind(new_character.user_id) + .bind(new_character.viewable) + .bind(new_character.character_name) + .bind(new_character.data_type) + .bind(new_character.data_version) + .bind(new_character.data) + .execute(self) .await?; Ok(()) } - async fn update_character_sheet(&self, character: Character) -> QueryResult<()> { - use crate::schema::characters::dsl::*; - self.run(move |conn| { - diesel::update(&character) - .set(data.eq(&character.data)) - .execute(conn) - }) - .await?; + async fn update_character_sheet<'a>(&self, character: &'a Character) -> Result<(), Error> { + sqlx::query("UPDATE characters set data = ? where id = ?") + .bind(&character.data) + .bind(character.id) + .execute(self) + .await?; Ok(()) } diff --git a/src/errors.rs b/src/errors.rs index 79b32ec..adce3ac 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -20,9 +20,6 @@ pub enum Error { #[error("invalid input")] InvalidInput, - #[error("query error: {0}")] - QueryError(#[from] diesel::result::Error), - #[error("serialization error: {0}")] SerializationError(#[from] prost::EncodeError), @@ -31,6 +28,12 @@ pub enum Error { #[error("i/o error: {0}")] IoError(#[from] std::io::Error), + + #[error("query error: {0}")] + QueryError(#[from] sqlx::Error), + + #[error("rocket error: {0}")] + RocketError(#[from] rocket::error::Error), } impl Error { diff --git a/src/main.rs b/src/main.rs index 6bb0262..a94618e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,9 +4,6 @@ extern crate rocket; #[macro_use] extern crate rocket_contrib; -#[macro_use] -extern crate diesel; - // Seemingly necessary to get serde::Serialize into scope for Prost // code generation. #[macro_use] @@ -20,10 +17,9 @@ pub mod db; pub mod errors; pub mod models; pub mod routes; -pub mod schema; #[rocket::main] -async fn main() -> Result<(), rocket::error::Error> { +async fn main() -> Result<(), crate::errors::Error> { let root_routes: Vec = { routes::root::routes() .into_iter() @@ -37,7 +33,8 @@ async fn main() -> Result<(), rocket::error::Error> { rocket::ignite() .attach(Template::fairing()) - .attach(db::TenebrousDbConn::fairing()) + //.attach(db::TenebrousDbConn::fairing()) + .manage(crate::db::create_pool().await?) .mount("/", root_routes) .mount("/characters", character_routes) .mount("/api", api_routes) @@ -52,4 +49,5 @@ async fn main() -> Result<(), rocket::error::Error> { .register(catchers) .launch() .await + .map_err(|e| e.into()) } diff --git a/src/models/characters.rs b/src/models/characters.rs index ca0bd75..3742a5c 100644 --- a/src/models/characters.rs +++ b/src/models/characters.rs @@ -1,8 +1,6 @@ use crate::errors::Error; use crate::models::proto::cofd::*; use crate::models::users::User; -use crate::schema::characters; -use diesel_derive_enum::DbEnum; use prost::bytes::BytesMut; use serde_derive::Serialize; use strum::{EnumIter, EnumString}; @@ -41,7 +39,8 @@ pub(crate) trait Visibility { } } -#[derive(DbEnum, Debug, Serialize, PartialEq, Clone, Copy, EnumIter, EnumString)] +#[derive(Debug, Serialize, PartialEq, Clone, Copy, EnumIter, EnumString, sqlx::Type)] +#[sqlx(rename_all = "snake_case")] pub enum CharacterDataType { ChroniclesOfDarknessV1, ChangelingV1, @@ -73,7 +72,7 @@ impl CharacterDataType { /// An entry that appears in a user's character list. Properties are /// in order of table columns. -#[derive(Serialize, Debug, Queryable, Identifiable, AsChangeset)] +#[derive(Serialize, Debug, sqlx::FromRow)] pub struct Character { pub id: i32, pub user_id: i32, @@ -145,7 +144,7 @@ impl Character { /// Same as regular character type, but without the actual protobuf /// data loaded into memory. -#[derive(Serialize, Debug, Queryable)] +#[derive(Serialize, Debug, sqlx::FromRow)] pub struct StrippedCharacter { pub id: i32, pub user_id: i32, @@ -167,13 +166,11 @@ impl Visibility for StrippedCharacter { /// Represents insert of a new character into the database. Property /// names correspond to columns. -#[derive(Insertable)] -#[table_name = "characters"] -pub struct NewCharacter { +pub struct NewCharacter<'a> { pub user_id: i32, pub viewable: bool, - pub character_name: String, + pub character_name: &'a str, pub data_type: CharacterDataType, pub data_version: i32, - pub data: Vec, + pub data: &'a [u8], } diff --git a/src/models/users.rs b/src/models/users.rs index ab0bb57..96278b1 100644 --- a/src/models/users.rs +++ b/src/models/users.rs @@ -1,5 +1,4 @@ use crate::db::{Dao, TenebrousDbConn}; -use crate::schema::users; use argon2::{self, Config, Error as ArgonError}; use rand::Rng; use rocket::outcome::IntoOutcome; @@ -12,7 +11,7 @@ pub(crate) fn hash_password(raw_password: &str) -> Result { argon2::hash_encoded(raw_password.as_bytes(), &salt, &config) } -#[derive(Eq, PartialEq, Serialize, Debug, Queryable)] +#[derive(Eq, PartialEq, Serialize, Debug, sqlx::FromRow)] pub struct User { pub id: i32, pub username: String, @@ -25,10 +24,11 @@ impl User { } } -async fn attempt_load_user<'a>(db: &'a TenebrousDbConn, id: i32) -> Option { +async fn attempt_load_user<'a>(db: &'a TenebrousDbConn<'a>, id: i32) -> Option { db.load_user_by_id(id).await.ok().flatten() } +/// Trait implementation to get the logged in user. #[rocket::async_trait] impl<'a, 'r> FromRequest<'a, 'r> for &'a User { type Error = (); @@ -53,9 +53,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for &'a User { } } -#[derive(Insertable)] -#[table_name = "users"] -pub struct NewUser { - pub username: String, - pub password: String, +pub struct NewUser<'a> { + pub username: &'a str, + pub password: &'a str, } diff --git a/src/routes/api.rs b/src/routes/api.rs index 0ebcabd..443485a 100644 --- a/src/routes/api.rs +++ b/src/routes/api.rs @@ -24,13 +24,13 @@ pub(crate) fn routes() -> Vec { /// logged in, the owner of the character is not found, or the logged /// in user does not have the permission to access this character. async fn load_character( - conn: &TenebrousDbConn, + conn: &TenebrousDbConn<'_>, logged_in_user: Option<&User>, owner: String, character_id: i32, ) -> Result { let logged_in_user = logged_in_user.ok_or(Error::NotLoggedIn)?; - let owner = conn.load_user(owner).await?.ok_or(Error::NotFound)?; + let owner = conn.load_user(&owner).await?.ok_or(Error::NotFound)?; let character: Character = conn .load_character(character_id) .await? @@ -71,7 +71,7 @@ mod cofd { owner: String, character_id: i32, attr_update: Proto, - conn: TenebrousDbConn, + conn: TenebrousDbConn<'_>, logged_in_user: Option<&User>, ) -> Result<&'a str, Error> { let mut character = load_character(&conn, logged_in_user, owner, character_id).await?; @@ -96,7 +96,7 @@ mod cofd { ); character.update_data(sheet)?; - conn.update_character_sheet(character).await?; + conn.update_character_sheet(&character).await?; Ok("lol") } @@ -105,7 +105,7 @@ mod cofd { owner: String, character_id: i32, info: Proto, - conn: TenebrousDbConn, + conn: TenebrousDbConn<'_>, ) -> &'a str { "lol" } diff --git a/src/routes/auth.rs b/src/routes/auth.rs index a1c9b21..c3f1d05 100644 --- a/src/routes/auth.rs +++ b/src/routes/auth.rs @@ -50,10 +50,10 @@ fn registration_error_redirect>(message: S) -> Flash { async fn login( cookies: &CookieJar<'_>, login: Form, - conn: TenebrousDbConn, + conn: TenebrousDbConn<'_>, ) -> Result> { let user = conn - .load_user(login.username.clone()) + .load_user(&login.username) .await .map_err(|e| { error!("login - error loading user user: {}", e); @@ -104,15 +104,12 @@ fn register_page(flash: Option) -> Template { async fn register( mut cookies: &CookieJar<'_>, registration: Form, - conn: TenebrousDbConn, + conn: TenebrousDbConn<'_>, ) -> Result> { - let existing_user = conn - .load_user(registration.username.clone()) - .await - .map_err(|e| { - error!("registration - error loading existing user: {}", e); - registration_error_redirect("There was an error attempting to register.") - })?; + let existing_user = conn.load_user(®istration.username).await.map_err(|e| { + error!("registration - error loading existing user: {}", e); + registration_error_redirect("There was an error attempting to register.") + })?; if existing_user.is_some() { return Err(registration_error_redirect(format!( @@ -127,8 +124,8 @@ async fn register( })?; let user = NewUser { - username: registration.username.clone(), - password: hashed_pw, + username: ®istration.username, + password: &hashed_pw, }; let user = conn.insert_user(user).await.map_err(|e| { diff --git a/src/routes/characters.rs b/src/routes/characters.rs index d28a0ad..f2bc09c 100644 --- a/src/routes/characters.rs +++ b/src/routes/characters.rs @@ -50,10 +50,10 @@ fn view_character_template(user: &User, character: Character) -> Result