From 64f4743053dc7efcfb2ecdf391c652877f2e0abc Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Wed, 3 Feb 2021 00:28:26 +0000 Subject: [PATCH] Implement user authentication --- Cargo.lock | 403 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- config.toml | 3 ++- titanirc-server/Cargo.toml | 3 ++- titanirc-server/migrations/001_initial.sql | 35 +++++++++++++++++++++++++++++++++++ titanirc-server/src/config.rs | 1 + titanirc-server/src/entities/user/commands.rs | 18 ++++++++++++++++-- titanirc-server/src/entities/user/mod.rs | 15 +++++++++++++++ titanirc-server/src/main.rs | 18 +++++++++++++++++- titanirc-server/src/models/mod.rs | 3 +++ titanirc-server/src/models/user.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ titanirc-server/src/server.rs | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- titanirc-types/src/protocol/commands.rs | 1 + titanirc-types/src/protocol/primitives.rs | 27 +++++++++++++++++++++++++++ 13 files changed, 363 insertions(+), 274 deletions(-) create mode 100644 titanirc-server/migrations/001_initial.sql create mode 100644 titanirc-server/src/models/mod.rs create mode 100644 titanirc-server/src/models/user.rs diff --git a/Cargo.lock b/Cargo.lock index dcd6b0f..22fe269 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ dependencies = [ "actix-rt", "actix_derive", "bitflags", - "bytes 1.0.1", + "bytes", "crossbeam-channel", "futures-core", "futures-sink", @@ -17,9 +17,9 @@ dependencies = [ "log", "once_cell", "parking_lot", - "pin-project-lite 0.2.4", + "pin-project-lite", "smallvec", - "tokio 1.1.1", + "tokio", "tokio-util", "trust-dns-proto", "trust-dns-resolver", @@ -52,7 +52,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac24f3f660d4c394cc6d24272e526083c257d6045d3be76a9d0a76be5cb56515" dependencies = [ "actix-macros 0.2.0-beta.1", - "tokio 1.1.1", + "tokio", +] + +[[package]] +name = "actix-threadpool" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d209f04d002854b9afd3743032a27b066158817965bf5d036824d19ac2cc0e30" +dependencies = [ + "derive_more", + "futures-channel", + "lazy_static", + "log", + "num_cpus", + "parking_lot", + "threadpool", ] [[package]] @@ -153,7 +168,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -164,9 +179,20 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "base64" -version = "0.12.3" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bcrypt" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4d0faafe9e089674fc3efdb311ff5253d445c79d85d1d28bd3ace76d45e7164" +dependencies = [ + "base64", + "blowfish", + "getrandom", +] [[package]] name = "bitflags" @@ -196,6 +222,17 @@ dependencies = [ ] [[package]] +name = "blowfish" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32fa6a061124e37baba002e496d203e23ba3d7b73750be82dbfbc92913048a5b" +dependencies = [ + "byteorder", + "cipher", + "opaque-debug", +] + +[[package]] name = "build_const" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -215,39 +252,11 @@ checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" [[package]] name = "bytes" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" - -[[package]] -name = "bytes" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" [[package]] -name = "cargo-platform" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0226944a63d1bf35a3b5f948dd7c59e263db83695c9e8bffc4037de02e30f1d7" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714a157da7991e23d90686b9524b9e12e0407a108647f52e9328f4b3d51ac7f" -dependencies = [ - "cargo-platform", - "semver", - "semver-parser", - "serde", - "serde_json", -] - -[[package]] name = "cc" version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -266,6 +275,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] +name = "cipher" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" +dependencies = [ + "generic-array", +] + +[[package]] name = "clap" version = "3.0.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -415,22 +433,6 @@ dependencies = [ ] [[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -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" @@ -524,7 +526,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.4", + "pin-project-lite", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -602,7 +604,7 @@ checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" dependencies = [ "libc", "match_cfg", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -636,15 +638,6 @@ dependencies = [ ] [[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - -[[package]] name = "ipconfig" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -652,7 +645,7 @@ checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" dependencies = [ "socket2", "widestring", - "winapi 0.3.9", + "winapi", "winreg", ] @@ -678,16 +671,6 @@ dependencies = [ ] [[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -713,6 +696,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff" [[package]] +name = "libsqlite3-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d31059f22935e6c31830db5249ba2b7ecd54fd73a9909286f0a67aa55c2fbd" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] name = "linked-hash-map" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -771,57 +765,15 @@ checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "mio" -version = "0.6.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" -dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log", - "miow 0.2.2", - "net2", - "slab", - "winapi 0.2.8", -] - -[[package]] -name = "mio" version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e50ae3f04d169fcc9bde0b547d1c205219b7157e07ded9c5aff03e0637cb3ed7" dependencies = [ "libc", "log", - "miow 0.3.6", + "miow", "ntapi", - "winapi 0.3.9", -] - -[[package]] -name = "mio-uds" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" -dependencies = [ - "iovec", - "libc", - "mio 0.6.23", -] - -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", + "winapi", ] [[package]] @@ -831,18 +783,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" dependencies = [ "socket2", - "winapi 0.3.9", -] - -[[package]] -name = "net2" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -862,7 +803,7 @@ name = "nom-bytes" version = "0.1.0" source = "git+https://github.com/w4/nom-bytes#7e44afde2e53f447fc9c77297eb513186b8fb0da" dependencies = [ - "bytes 1.0.1", + "bytes", "nom", ] @@ -872,7 +813,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -934,7 +875,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -950,21 +891,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] -name = "pest" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" -dependencies = [ - "ucd-trie", -] - -[[package]] -name = "pin-project-lite" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" - -[[package]] name = "pin-project-lite" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -977,6 +903,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + +[[package]] name = "ppv-lite86" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1134,14 +1066,14 @@ dependencies = [ "spin", "untrusted", "web-sys", - "winapi 0.3.9", + "winapi", ] [[package]] name = "rustls" -version = "0.18.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" +checksum = "064fd21ff87c6e87ed4506e68beb42459caa4a0e2eb144932e6776768556980b" dependencies = [ "base64", "log", @@ -1173,25 +1105,6 @@ dependencies = [ ] [[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", - "serde", -] - -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] - -[[package]] name = "serde" version = "1.0.123" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1212,17 +1125,6 @@ dependencies = [ ] [[package]] -name = "serde_json" -version = "1.0.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] name = "sha2" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1264,7 +1166,7 @@ checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" dependencies = [ "cfg-if 1.0.0", "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1289,8 +1191,7 @@ dependencies = [ [[package]] name = "sqlx" version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1a98f9bf17b690f026b6fec565293a995b46dfbd6293debcb654dcffd2d1b34" +source = "git+https://github.com/launchbadge/sqlx#31abe22e348d6ac668c140de32612f0930c2abec" dependencies = [ "sqlx-core", "sqlx-macros", @@ -1299,14 +1200,13 @@ dependencies = [ [[package]] name = "sqlx-core" version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36bb6a2ca3345a86493bc3b71eabc2c6c16a8bb1aa476cf5303bee27f67627d7" +source = "git+https://github.com/launchbadge/sqlx#31abe22e348d6ac668c140de32612f0930c2abec" dependencies = [ "ahash 0.6.3", "atoi", "bitflags", "byteorder", - "bytes 0.5.6", + "bytes", "crc", "crossbeam-channel", "crossbeam-queue", @@ -1319,6 +1219,7 @@ dependencies = [ "hex", "itoa", "libc", + "libsqlite3-sys", "log", "memchr", "once_cell", @@ -1331,6 +1232,7 @@ dependencies = [ "sqlx-rt", "stringprep", "thiserror", + "tokio-stream", "url", "webpki", "webpki-roots", @@ -1340,15 +1242,12 @@ dependencies = [ [[package]] name = "sqlx-macros" version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5ada8b3b565331275ce913368565a273a74faf2a34da58c4dc010ce3286844" +source = "git+https://github.com/launchbadge/sqlx#31abe22e348d6ac668c140de32612f0930c2abec" dependencies = [ - "cargo_metadata", "dotenv", "either", "futures", "heck", - "lazy_static", "proc-macro2", "quote", "sha2", @@ -1361,11 +1260,12 @@ dependencies = [ [[package]] name = "sqlx-rt" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63fc5454c9dd7aaea3a0eeeb65ca40d06d0d8e7413a8184f7c3a3ffa5056190b" +source = "git+https://github.com/launchbadge/sqlx#31abe22e348d6ac668c140de32612f0930c2abec" dependencies = [ + "actix-rt", + "actix-threadpool", "once_cell", - "tokio 0.2.25", + "tokio", "tokio-rustls", ] @@ -1456,6 +1356,15 @@ dependencies = [ ] [[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] name = "tinyvec" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1474,7 +1383,7 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" name = "titanirc-codec" version = "0.1.0" dependencies = [ - "bytes 1.0.1", + "bytes", "nom", "titanirc-types", "tokio-util", @@ -1488,7 +1397,8 @@ dependencies = [ "actix-rt", "arc-swap", "async-stream", - "bytes 1.0.1", + "bcrypt", + "bytes", "clap", "derive_more", "displaydoc", @@ -1498,7 +1408,7 @@ dependencies = [ "thiserror", "titanirc-codec", "titanirc-types", - "tokio 1.1.1", + "tokio", "tokio-util", "toml", "uuid", @@ -1509,7 +1419,7 @@ name = "titanirc-types" version = "0.1.0" dependencies = [ "arc-swap", - "bytes 1.0.1", + "bytes", "derive_more", "nom", "nom-bytes", @@ -1518,64 +1428,43 @@ dependencies = [ [[package]] name = "tokio" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092" -dependencies = [ - "bytes 0.5.6", - "futures-core", - "iovec", - "lazy_static", - "libc", - "memchr", - "mio 0.6.23", - "mio-uds", - "num_cpus", - "pin-project-lite 0.1.11", - "slab", - "tokio-macros", -] - -[[package]] -name = "tokio" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6714d663090b6b0acb0fa85841c6d66233d150cdb2602c8f9b8abb03370beb3f" dependencies = [ "autocfg", - "bytes 1.0.1", + "bytes", "libc", "memchr", - "mio 0.7.7", + "mio", "num_cpus", "once_cell", "parking_lot", - "pin-project-lite 0.2.4", + "pin-project-lite", "signal-hook-registry", - "winapi 0.3.9", + "winapi", ] [[package]] -name = "tokio-macros" -version = "0.2.6" +name = "tokio-rustls" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a" +checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" dependencies = [ - "proc-macro2", - "quote", - "syn", + "rustls", + "tokio", + "webpki", ] [[package]] -name = "tokio-rustls" -version = "0.14.1" +name = "tokio-stream" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a" +checksum = "76066865172052eb8796c686f0b441a93df8b08d40a950b062ffb9a426f00edd" dependencies = [ "futures-core", - "rustls", - "tokio 0.2.25", - "webpki", + "pin-project-lite", + "tokio", ] [[package]] @@ -1584,12 +1473,12 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebb7cb2f00c5ae8df755b252306272cd1790d39728363936e01827e11f0b017b" dependencies = [ - "bytes 1.0.1", + "bytes", "futures-core", "futures-sink", "log", - "pin-project-lite 0.2.4", - "tokio 1.1.1", + "pin-project-lite", + "tokio", ] [[package]] @@ -1621,7 +1510,7 @@ dependencies = [ "rand", "smallvec", "thiserror", - "tokio 1.1.1", + "tokio", "url", ] @@ -1641,7 +1530,7 @@ dependencies = [ "resolv-conf", "smallvec", "thiserror", - "tokio 1.1.1", + "tokio", "trust-dns-proto", ] @@ -1652,12 +1541,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] -name = "ucd-trie" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" - -[[package]] name = "unicode-bidi" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1727,6 +1610,12 @@ dependencies = [ ] [[package]] +name = "vcpkg" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" + +[[package]] name = "vec_map" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1845,12 +1734,6 @@ checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" [[package]] name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - -[[package]] -name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" @@ -1860,12 +1743,6 @@ dependencies = [ ] [[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - -[[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1877,7 +1754,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1892,17 +1769,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", + "winapi", ] [[package]] diff --git a/config.toml b/config.toml index 0c2a001..696f018 100644 --- a/config.toml +++ b/config.toml @@ -1 +1,2 @@ -socket_address = "0.0.0.0:6667" \ No newline at end of file +socket_address = "0.0.0.0:6667" +database_uri = "sqlite::memory:" \ No newline at end of file diff --git a/titanirc-server/Cargo.toml b/titanirc-server/Cargo.toml index 0bcf1c8..e054699 100644 --- a/titanirc-server/Cargo.toml +++ b/titanirc-server/Cargo.toml @@ -22,7 +22,8 @@ displaydoc = "0.1" clap = "3.0.0-beta.2" futures-util = "0.3" bytes = "1.0" +bcrypt = "0.9" uuid = { version = "0.8", features = ["v4"] } derive_more = "0.99" arc-swap = "1.2" -sqlx = { version = "0.4", features = [ "runtime-tokio-rustls", "any", "macros", "migrate" ] } +sqlx = { git = "https://github.com/launchbadge/sqlx", features = [ "runtime-actix-rustls", "sqlite" ] } diff --git a/titanirc-server/migrations/001_initial.sql b/titanirc-server/migrations/001_initial.sql new file mode 100644 index 0000000..807629f --- /dev/null +++ b/titanirc-server/migrations/001_initial.sql @@ -0,0 +1,35 @@ +CREATE TABLE channels ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT UNIQUE +); + +CREATE TABLE channel_opers ( + channel_id INTEGER NOT NULL, + user_id INTEGER NOT NULL, + level INTEGER NOT NULL, + FOREIGN KEY (channel_id) + REFERENCES channels (id), + FOREIGN KEY (user_id) + REFERENCES users (id) +); + +CREATE TABLE bans ( + mask BINARY PRIMARY KEY, + expires INTEGER, + created INTEGER DEFAULT CURRENT_TIMESTAMP, + revoked BOOLEAN DEFAULT false +); + +CREATE TABLE users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + password BINARY(60), + op BOOLEAN DEFAULT false +); + +CREATE TABLE users_aliases ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + nick TEXT UNIQUE, + user_id INT NOT NULL, + FOREIGN KEY (user_id) + REFERENCES users (id) +); \ No newline at end of file diff --git a/titanirc-server/src/config.rs b/titanirc-server/src/config.rs index 22c66cb..0d4711e 100644 --- a/titanirc-server/src/config.rs +++ b/titanirc-server/src/config.rs @@ -4,4 +4,5 @@ use std::net::SocketAddr; #[derive(Debug, Deserialize)] pub struct Config { pub socket_address: SocketAddr, + pub database_uri: String, } diff --git a/titanirc-server/src/entities/user/commands.rs b/titanirc-server/src/entities/user/commands.rs index af48848..a2a826d 100644 --- a/titanirc-server/src/entities/user/commands.rs +++ b/titanirc-server/src/entities/user/commands.rs @@ -5,7 +5,8 @@ use std::{sync::Arc, time::Instant}; use actix::{Actor, AsyncContext, StreamHandler}; use titanirc_types::protocol::{ commands::{ - Command, JoinCommand, ModeCommand, MotdCommand, NickCommand, PrivmsgCommand, VersionCommand, + Command, JoinCommand, ModeCommand, MotdCommand, NickCommand, PassCommand, PrivmsgCommand, + VersionCommand, }, primitives, replies::Reply, @@ -24,6 +25,7 @@ impl StreamHandler, std::io::Error>> for super::User { Ok(Command::Join(v)) => self.handle_cmd(v, ctx), Ok(Command::Mode(v)) => self.handle_cmd(v, ctx), Ok(Command::Motd(v)) => self.handle_cmd(v, ctx), + Ok(Command::Pass(v)) => self.handle_cmd(v, ctx), Ok(Command::Privmsg(v)) => self.handle_cmd(v, ctx), Ok(Command::Version(v)) => self.handle_cmd(v, ctx), Ok(Command::Pong(_)) => {} @@ -36,16 +38,28 @@ impl StreamHandler, std::io::Error>> for super::User { // TODO: all the 'raw' writes using byte strings below probably need to // be wrapped in something a bit more friendly. +impl CommandHandler> for super::User { + fn handle_cmd(&mut self, command: PassCommand<'static>, _ctx: &mut Self::Context) { + self.password_auth_in_progress = Some(command.password.to_bytes()); + } +} + impl CommandHandler> for super::User { fn handle_cmd( &mut self, NickCommand { nick, .. }: NickCommand<'static>, - _ctx: &mut Self::Context, + ctx: &mut Self::Context, ) { // TODO: when authenticated, the user should only be allowed to /NICK themselves // to unregistered nicks or aliases. self.nick.set(Arc::new(nick.to_bytes())); + self.server.do_send(crate::server::events::UserAuth { + nick: nick.to_bytes(), + user: ctx.address(), + password: self.password_auth_in_progress.clone().unwrap(), + }); + self.writer.write(Reply::RplWelcome.into()); self.writer.write(Reply::RplYourHost.into()); self.writer.write(Reply::RplCreated.into()); diff --git a/titanirc-server/src/entities/user/mod.rs b/titanirc-server/src/entities/user/mod.rs index 388c2ac..9657cdc 100644 --- a/titanirc-server/src/entities/user/mod.rs +++ b/titanirc-server/src/entities/user/mod.rs @@ -39,6 +39,8 @@ pub struct User { pub last_active: Instant, pub nick: RegisteredNick, + pub password_auth_in_progress: Option, + pub channels: HashMap, } @@ -54,6 +56,7 @@ impl User { session_id: UserUuid(Uuid::new_v4()), server, writer, + password_auth_in_progress: None, last_active: Instant::now(), nick, channels: HashMap::new(), @@ -87,6 +90,18 @@ impl Actor for User { /// Handles errors from our socket Writer. impl WriteHandler for User {} +impl actix::Handler for User { + type Result = (); + + fn handle( + &mut self, + msg: crate::server::events::UserAuthResponse, + ctx: &mut Self::Context, + ) -> Self::Result { + todo!() + } +} + impl actix::Handler for User { type Result = (); diff --git a/titanirc-server/src/main.rs b/titanirc-server/src/main.rs index 60522fe..95b5935 100644 --- a/titanirc-server/src/main.rs +++ b/titanirc-server/src/main.rs @@ -4,6 +4,7 @@ mod config; mod entities; mod error; +mod models; mod server; use std::path::PathBuf; @@ -16,9 +17,12 @@ use crate::{ use actix::{Actor, AsyncContext, System}; use clap::Clap; use displaydoc::Display; +use sqlx::migrate::Migrator; use thiserror::Error; use tokio::net::TcpListener; +static MIGRATOR: Migrator = sqlx::migrate!(); + #[derive(Error, Debug, Display)] pub enum InitError { /// Failed to bind to socket: {0} @@ -27,6 +31,10 @@ pub enum InitError { ConfigRead(std::io::Error), /// Failed to parse config file: {0} ConfigParse(toml::de::Error), + /// Failed to connect to database: {0} + SqlConnect(sqlx::Error), + /// Failed to run migrations against the database: {0} + SqlMigrate(sqlx::migrate::MigrateError), } #[derive(Clap)] @@ -44,6 +52,14 @@ async fn main() -> Result<()> { let config = std::fs::read(&opts.config).map_err(InitError::ConfigRead)?; let config: config::Config = toml::from_slice(&config).map_err(InitError::ConfigParse)?; + let sql_pool = sqlx::SqlitePool::connect(&config.database_uri) + .await + .map_err(InitError::SqlConnect)?; + MIGRATOR + .run(&sql_pool) + .await + .map_err(InitError::SqlMigrate)?; + let listener = TcpListener::bind(&config.socket_address) .await .map_err(InitError::TcpBind)?; @@ -61,7 +77,7 @@ async fn main() -> Result<()> { // Spawn the server and pass connections from `stream` to `Handler`. Server::create(move |ctx| { ctx.add_message_stream(stream); - Server::new() + Server::new(sql_pool) }); println!("Running IRC server on {}", &config.socket_address); diff --git a/titanirc-server/src/models/mod.rs b/titanirc-server/src/models/mod.rs new file mode 100644 index 0000000..4d941e2 --- /dev/null +++ b/titanirc-server/src/models/mod.rs @@ -0,0 +1,3 @@ +//! Database access models + +pub mod user; diff --git a/titanirc-server/src/models/user.rs b/titanirc-server/src/models/user.rs new file mode 100644 index 0000000..18f8c27 --- /dev/null +++ b/titanirc-server/src/models/user.rs @@ -0,0 +1,48 @@ +#[derive(sqlx::FromRow)] +pub struct User { + id: u64, + password: String, + op: bool, +} + +impl User { + pub async fn create_user( + conn: &sqlx::SqlitePool, + nick: &[u8], + password: bytes::Bytes, + ) -> Result<(), sqlx::Error> { + let mut tx = conn.begin().await?; + + sqlx::query("INSERT INTO users (password) VALUES (?)") + .bind( + tokio::task::spawn_blocking(move || bcrypt::hash(&password, 10).unwrap()) + .await + .unwrap(), + ) + .execute(&mut tx) + .await?; + + sqlx::query("INSERT INTO users_aliases (nick, user_id) VALUES (?, LAST_INSERT_ROWID())") + .bind(nick) + .execute(&mut tx) + .await?; + + tx.commit().await?; + + Ok(()) + } + + pub async fn fetch_by_nick( + conn: &sqlx::SqlitePool, + nick: &[u8], + ) -> Result, sqlx::Error> { + sqlx::query_as::<_, Self>("SELECT * FROM users WHERE users.id = (SELECT user_id FROM users_aliases WHERE nick = ?)") + .bind(&nick) + .fetch_optional(conn) + .await + } + + pub fn password_matches(&self, password: &[u8]) -> bool { + bcrypt::verify(password, &self.password).unwrap() + } +} diff --git a/titanirc-server/src/server.rs b/titanirc-server/src/server.rs index 756db93..b3226be 100644 --- a/titanirc-server/src/server.rs +++ b/titanirc-server/src/server.rs @@ -17,6 +17,8 @@ use tokio_util::codec::FramedRead; /// /// Essentially acts as the middleman for each entity communicating with each other. pub struct Server { + sql_pool: sqlx::SqlitePool, + /// A list of known channels and the addresses to them. pub channels: HashMap>, // A list of known connected users. @@ -24,8 +26,9 @@ pub struct Server { } impl Server { - pub fn new() -> Self { + pub fn new(sql_pool: sqlx::SqlitePool) -> Self { Self { + sql_pool, channels: HashMap::new(), // users: Vec::new(), } @@ -109,3 +112,60 @@ impl Handler for Server { todo!() } } + +impl Handler for Server { + type Result = (); + + fn handle(&mut self, msg: events::UserAuth, ctx: &mut Self::Context) -> Self::Result { + let conn = self.sql_pool.clone(); + + ctx.spawn( + async move { + match crate::models::user::User::fetch_by_nick(&conn, &msg.nick).await { + Ok(Some(user)) => { + if user.password_matches(&msg.password) { + eprintln!("user authed"); + } else { + eprintln!("user not authed"); + } + } + Ok(None) => { + let passwd = msg.password.clone(); + if let Err(e) = + crate::models::user::User::create_user(&conn, &msg.nick, passwd).await + { + eprintln!("failed to create user: {:?}", e); + } else { + eprintln!("successfully registered"); + } + } + Err(e) => { + eprintln!("failed to fetch by nick: {:?} ", e) + } + } + } + .into_actor(self), + ); + } +} + +pub mod events { + use actix::{Addr, Message}; + + use crate::entities::user::User; + + #[derive(Message)] + #[rtype(result = "")] + pub struct UserAuth { + pub user: Addr, + pub nick: bytes::Bytes, + pub password: bytes::Bytes, + } + + #[derive(Message)] + #[rtype(result = "")] + pub enum UserAuthResponse { + Valid, + InvalidPassword, + } +} diff --git a/titanirc-types/src/protocol/commands.rs b/titanirc-types/src/protocol/commands.rs index dd3e732..45448c9 100644 --- a/titanirc-types/src/protocol/commands.rs +++ b/titanirc-types/src/protocol/commands.rs @@ -115,6 +115,7 @@ macro_rules! define_commands { } define_commands! { + PASS(Password<'a>), USER(Username<'a>, HostName<'a>, ServerName<'a>, RealName<'a>), NICK(Nick<'a>), diff --git a/titanirc-types/src/protocol/primitives.rs b/titanirc-types/src/protocol/primitives.rs index 66cf347..9f4cb38 100644 --- a/titanirc-types/src/protocol/primitives.rs +++ b/titanirc-types/src/protocol/primitives.rs @@ -95,6 +95,28 @@ macro_rules! free_text_primitive { }; } +macro_rules! free_text_primitive_no_colon { + ($name:ty) => { + impl PrimitiveParser for $name { + fn parse(bytes: BytesWrapper) -> IResult { + Ok((Bytes::new().into(), Self(bytes.into()))) + } + } + + impl std::fmt::Display for $name { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match std::str::from_utf8(&self.0[..]) { + Ok(v) => f.write_str(v), + Err(_e) => { + eprintln!("Invalid utf-8 in {}", stringify!($name)); + Err(std::fmt::Error) + } + } + } + } + }; +} + macro_rules! space_terminated_primitive { ($name:ty) => { impl PrimitiveParser for $name { @@ -180,6 +202,11 @@ impl ValidatingParser for Special { } #[derive(Debug, Deref, Clone, From)] +pub struct Password<'a>(pub BytesCow<'a>); +free_text_primitive_no_colon!(Password<'_>); +noop_validator!(Password<'_>); + +#[derive(Debug, Deref, Clone, From)] pub struct Username<'a>(pub BytesCow<'a>); space_terminated_primitive!(Username<'_>); noop_validator!(Username<'_>); -- libgit2 1.7.2