From be96100237da56313a583be6da3dc27a4371e29d Mon Sep 17 00:00:00 2001 From: Joe Ardent Date: Tue, 20 Jun 2023 16:32:36 -0700 Subject: [PATCH] mostly done, but logins aren't working --- Cargo.lock | 320 +++++++++++++++++----------------------- Cargo.toml | 2 +- src/db.rs | 5 +- src/ids.rs | 143 ++++++++++++++++++ src/lib.rs | 5 +- src/signup.rs | 22 +-- src/test_utils.rs | 5 +- src/users.rs | 11 +- src/watches/handlers.rs | 12 +- src/watches/mod.rs | 19 +-- 10 files changed, 316 insertions(+), 228 deletions(-) create mode 100644 src/ids.rs diff --git a/Cargo.lock b/Cargo.lock index 19f09b0..7b83a10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,6 +24,18 @@ dependencies = [ "version_check", ] +[[package]] +name = "allocator-api2" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56fc6cf8dc8c4158eed8649f9b8b0ea1518eb62b544fe9490d66fa0b349eafe9" + +[[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" @@ -179,7 +191,7 @@ dependencies = [ "async-trait", "axum-core", "axum-macros", - "bitflags", + "bitflags 1.3.2", "bytes", "futures-util", "headers", @@ -239,7 +251,7 @@ dependencies = [ "serde", "tokio", "tower", - "tower-http 0.4.0", + "tower-http 0.4.1", "tower-layer", "tower-service", ] @@ -298,9 +310,9 @@ dependencies = [ [[package]] name = "axum-test" -version = "9.0.0" +version = "9.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a01b0885dcea3124d990b24fd5ad9d0735f77d53385161665a0d9fd08a03e6" +checksum = "8822bb73c863cdc96a4476fdae6443495c9c312f9f659720aa4ea59d76074577" dependencies = [ "anyhow", "auto-future", @@ -355,6 +367,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbe3c979c178231552ecba20214a8272df4e09f232a87aef4320cf06539aded" + [[package]] name = "blake2" version = "0.10.6" @@ -435,12 +453,12 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.24" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" dependencies = [ + "android-tzdata", "iana-time-zone", - "num-integer", "num-traits", "serde", "winapi", @@ -462,7 +480,7 @@ dependencies = [ "hmac 0.12.1", "percent-encoding", "rand", - "sha2 0.10.6", + "sha2 0.10.7", "subtle", "time", "version_check", @@ -476,9 +494,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" dependencies = [ "libc", ] @@ -510,9 +528,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if 1.0.0", ] @@ -621,9 +639,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -740,9 +758,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if 1.0.0", "libc", @@ -757,20 +775,21 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.13.2" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" dependencies = [ "ahash 0.8.3", + "allocator-api2", ] [[package]] name = "hashlink" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0761a1b9491c4f2e3d66aa0f62d0fba0af9a0e2852e4d48ea506632a4b56e6aa" +checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f" dependencies = [ - "hashbrown 0.13.2", + "hashbrown 0.14.0", ] [[package]] @@ -780,7 +799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" dependencies = [ "base64 0.13.1", - "bitflags", + "bitflags 1.3.2", "bytes", "headers-core", "http", @@ -915,9 +934,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.56" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -938,9 +957,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -988,9 +1007,9 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "js-sys" -version = "0.3.63" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -1014,9 +1033,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.144" +version = "0.2.146" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" [[package]] name = "libm" @@ -1037,9 +1056,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -1047,9 +1066,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.18" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "matchers" @@ -1096,13 +1115,13 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "mio" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eebffdb73fe72e917997fad08bdbf31ac50b0fa91cec93e69a0662e4264d454c" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1125,16 +1144,6 @@ dependencies = [ "winapi", ] -[[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" @@ -1156,9 +1165,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "opaque-debug" @@ -1198,7 +1207,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.7", + "parking_lot_core 0.9.8", ] [[package]] @@ -1210,22 +1219,22 @@ dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "smallvec", "winapi", ] [[package]] name = "parking_lot_core" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall", + "redox_syscall 0.3.5", "smallvec", - "windows-sys 0.45.0", + "windows-targets", ] [[package]] @@ -1247,9 +1256,9 @@ checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project" @@ -1306,9 +1315,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" +checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" dependencies = [ "unicode-ident", ] @@ -1358,14 +1367,23 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", ] [[package]] name = "regex" -version = "1.8.3" +version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390" +checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" dependencies = [ "regex-syntax 0.7.2", ] @@ -1466,18 +1484,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ "proc-macro2", "quote", @@ -1486,9 +1504,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "bdf3bf93142acad5821c99197022e170842cdbc1c30482b98750c688c640842a" dependencies = [ "itoa", "ryu", @@ -1542,9 +1560,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -1638,7 +1656,7 @@ checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" dependencies = [ "ahash 0.7.6", "atoi", - "bitflags", + "bitflags 1.3.2", "byteorder", "bytes", "chrono", @@ -1666,7 +1684,7 @@ dependencies = [ "percent-encoding", "rustls", "rustls-pemfile", - "sha2 0.10.6", + "sha2 0.10.7", "smallvec", "sqlformat", "sqlx-rt", @@ -1691,7 +1709,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "sha2 0.10.6", + "sha2 0.10.7", "sqlx-core", "sqlx-rt", "syn 1.0.109", @@ -1785,9 +1803,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.21" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" +checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" dependencies = [ "itoa", "serde", @@ -1842,7 +1860,7 @@ dependencies = [ "socket2", "tokio-macros", "tracing", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1901,7 +1919,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" dependencies = [ "base64 0.13.1", - "bitflags", + "bitflags 1.3.2", "bytes", "futures-core", "futures-util", @@ -1915,11 +1933,11 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d1d42a9b3f3ec46ba828e8d376aec14592ea199f70a06a548587ecd1c4ab658" +checksum = "a8bd22a874a2d0b70452d5597b12c537331d49060824a95f49f108994f94aa4c" dependencies = [ - "bitflags", + "bitflags 2.3.2", "bytes", "futures-core", "futures-util", @@ -1959,9 +1977,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "8803eee176538f94ae9a14b55b2804eb7e1441f8210b1c31290b3bccdccff73b" dependencies = [ "proc-macro2", "quote", @@ -2019,6 +2037,15 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +[[package]] +name = "ulid" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13a3aaa69b04e5b66cc27309710a569ea23593612387d67daaf102e73aa974fd" +dependencies = [ + "rand", +] + [[package]] name = "unicase" version = "2.6.0" @@ -2069,9 +2096,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" dependencies = [ "form_urlencoded", "idna", @@ -2080,13 +2107,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.3.3" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" -dependencies = [ - "getrandom", - "serde", -] +checksum = "0fa2982af2eec27de306107c027578ff7f423d65f7250e40ce0fea8f45248b81" [[package]] name = "valuable" @@ -2108,11 +2131,10 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] @@ -2124,9 +2146,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -2134,9 +2156,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", @@ -2149,9 +2171,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2159,9 +2181,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", @@ -2172,15 +2194,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "web-sys" -version = "0.3.63" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ "js-sys", "wasm-bindgen", @@ -2233,16 +2255,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", + "windows-targets", ] [[package]] @@ -2251,22 +2264,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets", ] [[package]] @@ -2275,93 +2273,51 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" @@ -2389,11 +2345,11 @@ dependencies = [ "thiserror", "tokio", "tower", - "tower-http 0.4.0", + "tower-http 0.4.1", "tracing", "tracing-subscriber", + "ulid", "unicode-segmentation", - "uuid", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index c97229e..954e241 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,6 @@ tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } tower = { version = "0.4", features = ["util", "timeout"], default-features = false } tower-http = { version = "0.4", features = ["add-extension", "trace"] } -uuid = { version = "1", features = ["serde", "v4"] } serde = { version = "1", features = ["derive"] } sqlx = { version = "0.6", default-features = false, features = ["runtime-tokio-rustls", "any", "sqlite", "chrono", "time", "uuid"] } argon2 = "0.5" @@ -24,6 +23,7 @@ password-hash = { version = "0.5", features = ["std", "getrandom"] } axum-login = { version = "0.5", features = ["sqlite", "sqlx"] } unicode-segmentation = "1" async-session = "3" +ulid = { version = "1.0.0", features = ["rand"] } # proc macros: optional_optional_user = {path = "optional_optional_user"} diff --git a/src/db.rs b/src/db.rs index 6129518..4cbe8ae 100644 --- a/src/db.rs +++ b/src/db.rs @@ -11,9 +11,8 @@ use sqlx::{ sqlite::{SqliteConnectOptions, SqlitePoolOptions}, SqlitePool, }; -use uuid::Uuid; -use crate::User; +use crate::{ids::DbId, User}; const MAX_CONNS: u32 = 200; const MIN_CONNS: u32 = 5; @@ -105,7 +104,7 @@ pub async fn session_layer(pool: SqlitePool, secret: &[u8]) -> SessionLayer AuthLayer, Uuid, User> { +) -> AuthLayer, DbId, User> { const QUERY: &str = "select * from witches where id = $1"; let store = SqliteStore::::new(pool).with_query(QUERY); AuthLayer::new(store, secret) diff --git a/src/ids.rs b/src/ids.rs new file mode 100644 index 0000000..b8d4912 --- /dev/null +++ b/src/ids.rs @@ -0,0 +1,143 @@ +use std::{borrow::Cow, fmt::Display}; + +use serde::{de::Visitor, Deserialize, Serialize}; +use sqlx::{ + encode::IsNull, + sqlite::{SqliteArgumentValue, SqliteValueRef}, + Decode, Encode, Sqlite, +}; +use ulid::Ulid; + +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct DbId(pub Ulid); + +impl From for DbId { + fn from(value: Ulid) -> Self { + DbId(value) + } +} + +impl sqlx::Type for DbId { + fn type_info() -> ::TypeInfo { + <&[u8] as sqlx::Type>::type_info() + } +} + +impl<'q> Encode<'q, Sqlite> for DbId { + fn encode(self, args: &mut Vec>) -> IsNull { + args.push(SqliteArgumentValue::Blob(Cow::Owned(self.bytes().to_vec()))); + IsNull::No + } + + fn encode_by_ref(&self, args: &mut Vec>) -> IsNull { + args.push(SqliteArgumentValue::Blob(Cow::Owned(self.bytes().to_vec()))); + + IsNull::No + } + + fn produces(&self) -> Option<::TypeInfo> { + // `produces` is inherently a hook to allow database drivers to produce + // value-dependent type information; if the driver doesn't need this, it + // can leave this as `None` + None + } + + fn size_hint(&self) -> usize { + std::mem::size_of_val(self) + } +} + +impl<'r> Decode<'r, Sqlite> for DbId { + fn decode(value: SqliteValueRef<'r>) -> Result { + let bytes = <&[u8] as Decode>::decode(value)?; + let bytes: [u8; 16] = bytes.try_into().unwrap_or_default(); + let id: Ulid = u128::from_ne_bytes(bytes).into(); + Ok(id.into()) + } +} + +impl Display for DbId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0.to_string()) + } +} + +impl DbId { + pub fn bytes(&self) -> [u8; 16] { + self.0 .0.to_ne_bytes() + } + + pub fn is_nil(&self) -> bool { + self.0.is_nil() + } + + pub fn new() -> Self { + let id = Ulid::new(); + Self(id) + } +} + +impl Serialize for DbId { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_bytes(&self.0 .0.to_ne_bytes()) + } +} + +struct IdVisitor; + +impl<'de> Visitor<'de> for IdVisitor { + type Value = DbId; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a 128-bit number") + } + + fn visit_i128(self, v: i128) -> Result + where + E: serde::de::Error, + { + Ok(DbId(Ulid(v as u128))) + } + + fn visit_u128(self, v: u128) -> Result + where + E: serde::de::Error, + { + Ok(DbId(Ulid(v))) + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: serde::de::Error, + { + match std::convert::TryInto::<[u8; 16]>::try_into(v) { + Ok(v) => Ok(DbId(Ulid(u128::from_ne_bytes(v)))), + Err(_) => Err(serde::de::Error::invalid_length(v.len(), &self)), + } + } + + fn visit_string(self, v: String) -> Result + where + E: serde::de::Error, + { + match Ulid::from_string(&v) { + Ok(v) => Ok(DbId(v)), + Err(_) => Err(serde::de::Error::invalid_value( + serde::de::Unexpected::Str(&format!("could not convert {v} to a ULID")), + &self, + )), + } + } +} + +impl<'de> Deserialize<'de> for DbId { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_bytes(IdVisitor) + } +} diff --git a/src/lib.rs b/src/lib.rs index 952383a..ce5fb1c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ pub use db::get_db_pool; // everything else is private to the crate mod db; mod generic_handlers; +mod ids; mod login; mod signup; mod templates; @@ -18,6 +19,7 @@ mod util; mod watches; // things we want in the crate namespace +use ids::DbId; use optional_optional_user::OptionalOptionalUser; use templates::*; use users::User; @@ -25,8 +27,7 @@ use watches::{templates::*, ShowKind, Watch}; use crate::watches::handlers::get_watch; -type AuthContext = - axum_login::extractors::AuthContext>; +type AuthContext = axum_login::extractors::AuthContext>; /// Returns the router to be used as a service or test object, you do you. pub async fn app(db_pool: sqlx::SqlitePool, session_secret: &[u8]) -> axum::Router { diff --git a/src/signup.rs b/src/signup.rs index f16084f..40c879c 100644 --- a/src/signup.rs +++ b/src/signup.rs @@ -8,10 +8,10 @@ use axum::{ response::{IntoResponse, Response}, }; use sqlx::{query_as, SqlitePool}; +use ulid::Ulid; use unicode_segmentation::UnicodeSegmentation; -use uuid::Uuid; -use crate::{CreateUser, CreateUserSuccess, User}; +use crate::{CreateUser, CreateUserSuccess, DbId, User}; pub(crate) const CREATE_QUERY: &str = "insert into witches (id, username, displayname, email, pwhash) values ($1, $2, $3, $4, $5)"; @@ -96,9 +96,11 @@ pub async fn post_create_user( let email = validate_optional_length(&signup.email, 5..30, CreateUserErrorKind::BadEmail)?; - let user = create_user(username, &displayname, &email, password, &pool).await?; + let id = DbId::new(); + + let user = create_user(username, &displayname, &email, password, &pool, id).await?; tracing::debug!("created {user:?}"); - let id = user.id.as_simple().to_string(); + let id = user.id.0.to_string(); let location = format!("/signup_success/{id}"); let resp = axum::response::Redirect::to(&location); @@ -113,9 +115,9 @@ pub async fn get_signup_success( ) -> Response { let id = id.trim(); let user: User = { - let id = Uuid::try_parse(id).unwrap_or_default(); + let id: DbId = Ulid::from_string(id).unwrap_or_default().into(); query_as(ID_QUERY) - .bind(id) + .bind(id.bytes().as_slice()) .fetch_one(&pool) .await .unwrap_or_default() @@ -142,6 +144,7 @@ pub(crate) async fn create_user( email: &Option, password: &[u8], pool: &SqlitePool, + id: DbId, ) -> Result { // Argon2 with default params (Argon2id v19) let argon2 = Argon2::default(); @@ -151,10 +154,9 @@ pub(crate) async fn create_user( .unwrap() // safe to unwrap, we know the salt is valid .to_string(); - // TODO: look into ULIDs for sortable identifiers that are UUID-compatible - let id = Uuid::new_v4(); + let bytes = &id.bytes(); let query = sqlx::query(CREATE_QUERY) - .bind(id) + .bind(bytes.as_slice()) .bind(username) .bind(displayname) .bind(email) @@ -246,7 +248,7 @@ mod test { let user = get_test_user(); insert_user(&user, &pool).await; - let id = user.id.as_simple().to_string(); + let id = user.id.0.to_string(); let path = format!("/signup_success/{id}"); diff --git a/src/test_utils.rs b/src/test_utils.rs index 94d6378..e3657eb 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -1,9 +1,8 @@ use axum::body::Bytes; use axum_test::{TestServer, TestServerConfig}; use sqlx::SqlitePool; -use uuid::Uuid; -use crate::User; +use crate::{DbId, User}; pub const FORM_CONTENT_TYPE: &str = "application/x-www-form-urlencoded"; @@ -12,7 +11,7 @@ pub fn get_test_user() -> User { username: "test_user".to_string(), // corresponding to a password of "a": pwhash: "$argon2id$v=19$m=19456,t=2,p=1$GWsCH1w5RYaP9WWmq+xw0g$hmOEqC+MU+vnEk3bOdkoE+z01mOmmOeX08XyPyjqua8".to_string(), - id: Uuid::nil(), + id: DbId::default(), displayname: Some("Test User".to_string()), ..Default::default() } diff --git a/src/users.rs b/src/users.rs index 433130c..cb97cc9 100644 --- a/src/users.rs +++ b/src/users.rs @@ -7,16 +7,15 @@ use axum::{extract::State, http::Request, middleware::Next, response::IntoRespon use axum_login::{secrecy::SecretVec, AuthUser}; use serde::{Deserialize, Serialize}; use sqlx::SqlitePool; -use uuid::Uuid; -use crate::AuthContext; +use crate::{AuthContext, DbId}; const USERNAME_QUERY: &str = "select * from witches where username = $1"; const LAST_SEEN_QUERY: &str = "update witches set last_seen = (select unixepoch()) where id = $1"; #[derive(Default, Clone, PartialEq, Eq, sqlx::FromRow, Serialize, Deserialize)] pub struct User { - pub id: Uuid, + pub id: DbId, pub username: String, pub displayname: Option, pub email: Option, @@ -50,8 +49,8 @@ impl Display for User { } } -impl AuthUser for User { - fn get_id(&self) -> Uuid { +impl AuthUser for User { + fn get_id(&self) -> DbId { self.id } @@ -76,7 +75,7 @@ impl User { { Ok(_) => {} Err(e) => { - let id = self.id.as_simple(); + let id = self.id.0.to_string(); tracing::error!("Could not update last_seen for user {id}; got {e:?}"); } } diff --git a/src/watches/handlers.rs b/src/watches/handlers.rs index d37c991..38e7c37 100644 --- a/src/watches/handlers.rs +++ b/src/watches/handlers.rs @@ -5,10 +5,10 @@ use axum::{ }; use serde::{de, Deserialize, Deserializer}; use sqlx::{query, query_as, SqlitePool}; -use uuid::Uuid; +use ulid::Ulid; use super::templates::{AddNewWatchPage, GetWatchPage, SearchWatchesPage}; -use crate::{AuthContext, MyWatchesPage, ShowKind, Watch}; +use crate::{ids::DbId, AuthContext, MyWatchesPage, ShowKind, Watch}; //-************************************************************************ // Constants @@ -113,8 +113,8 @@ pub async fn post_add_new_watch( ) -> Result { if let Some(user) = auth.current_user { { - let watch_id = Uuid::new_v4(); - let witch_watch_id = Uuid::new_v4(); + let watch_id = DbId::new(); + let witch_watch_id = DbId::new(); let mut tx = pool .begin() .await @@ -149,7 +149,7 @@ pub async fn post_add_new_watch( tracing::error!("Got error: {err}"); WatchAddErrorKind::UnknownDBError })?; - let id = watch_id.simple(); + let id = watch_id.to_string(); let location = format!("/watch/{id}"); Ok(Redirect::to(&location)) } @@ -178,7 +178,7 @@ pub async fn get_watch( "".to_string() }; let id = id.trim(); - let id = Uuid::try_parse(id).unwrap_or_default(); + let id: DbId = Ulid::from_string(id).unwrap_or_default().into(); let watch: Option = query_as(GET_WATCH_QUERY) .bind(id) .fetch_one(&pool) diff --git a/src/watches/mod.rs b/src/watches/mod.rs index 5107164..915c69c 100644 --- a/src/watches/mod.rs +++ b/src/watches/mod.rs @@ -1,5 +1,6 @@ use serde::{Deserialize, Serialize}; -use uuid::Uuid; + +use crate::DbId; pub mod handlers; pub mod templates; @@ -65,25 +66,13 @@ impl From for ShowKind { sqlx::FromRow, )] pub struct Watch { - pub id: Uuid, + pub id: DbId, pub kind: ShowKind, pub title: String, pub metadata_url: Option, pub length: Option, pub release_date: Option, - added_by: Uuid, // this shouldn't be exposed to randos + added_by: DbId, // this shouldn't be exposed to randos created_at: i64, last_updated: i64, } - -impl Watch { - pub fn new(title: &str, added_by: Uuid) -> Self { - let id = Uuid::new_v4(); - Self { - id, - title: title.to_string(), - added_by, - ..Default::default() - } - } -}