From c742b752140ab0eee6e353c779bd897042ba6739 Mon Sep 17 00:00:00 2001 From: Cara Salter Date: Tue, 19 Jul 2022 19:49:39 -0400 Subject: Big login system Still needs cookies, but those are coming! (and should be set anyways!) --- Cargo.lock | 384 ++++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 5 +- scss/style.scss | 37 ++++- src/config.rs | 1 + src/errors.rs | 6 +- src/handlers/auth.rs | 79 ++++++++++ src/handlers/mod.rs | 16 ++ src/main.rs | 3 + src/models.rs | 12 ++ templates/footer.rs.html | 7 + templates/header.rs.html | 14 ++ templates/index.rs.html | 21 +-- templates/login.rs.html | 22 +++ templates/register.rs.html | 27 ++++ 14 files changed, 592 insertions(+), 42 deletions(-) create mode 100644 src/handlers/auth.rs create mode 100644 src/handlers/mod.rs create mode 100644 src/models.rs create mode 100644 templates/footer.rs.html create mode 100644 templates/header.rs.html create mode 100644 templates/login.rs.html create mode 100644 templates/register.rs.html diff --git a/Cargo.lock b/Cargo.lock index 6d31ed5..dfe189f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,41 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if 1.0.0", + "cipher 0.3.0", + "cpufeatures", + "opaque-debug", +] + +[[package]] +name = "aes-gcm" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" +dependencies = [ + "aead", + "aes", + "cipher 0.3.0", + "ctr", + "ghash", + "subtle", +] + [[package]] name = "ahash" version = "0.7.6" @@ -37,6 +72,54 @@ dependencies = [ "winapi", ] +[[package]] +name = "anyhow" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "async-lock" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-session" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07da4ce523b4e2ebaaf330746761df23a465b951a83d84bbce4233dabedae630" +dependencies = [ + "anyhow", + "async-lock", + "async-trait", + "base64", + "bincode", + "blake3", + "chrono", + "hmac 0.11.0", + "log", + "rand", + "serde", + "serde_json", + "sha2 0.9.9", +] + [[package]] name = "async-trait" version = "0.1.56" @@ -116,6 +199,7 @@ checksum = "277c75e6c814b061ae4947d02335d9659db9771b9950cca670002ae986372f44" dependencies = [ "axum", "bytes", + "cookie", "futures-util", "http", "mime", @@ -147,7 +231,7 @@ checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" dependencies = [ "addr2line", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", @@ -160,12 +244,57 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "bcrypt" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7e7c93a3fb23b2fdde989b2c9ec4dd153063ec81f408507f84c090cd91c6641" +dependencies = [ + "base64", + "blowfish", + "getrandom", + "zeroize", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "blake3" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if 0.1.10", + "constant_time_eq", + "crypto-mac 0.8.0", + "digest 0.9.0", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + [[package]] name = "block-buffer" version = "0.10.2" @@ -175,6 +304,16 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blowfish" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" +dependencies = [ + "byteorder", + "cipher 0.4.3", +] + [[package]] name = "bumpalo" version = "3.10.0" @@ -205,6 +344,12 @@ version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -220,10 +365,30 @@ dependencies = [ "libc", "num-integer", "num-traits", - "time", + "serde", + "time 0.1.44", "winapi", ] +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cipher" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "color-eyre" version = "0.6.2" @@ -251,6 +416,27 @@ dependencies = [ "tracing-error", ] +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "cookie" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" +dependencies = [ + "aes-gcm", + "base64", + "percent-encoding", + "rand", + "subtle", + "time 0.3.11", + "version_check", +] + [[package]] name = "cpufeatures" version = "0.2.2" @@ -281,7 +467,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crossbeam-utils", ] @@ -291,7 +477,7 @@ version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", ] @@ -305,13 +491,51 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "ctr" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher 0.3.0", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ - "block-buffer", + "block-buffer 0.10.2", "crypto-common", "subtle", ] @@ -457,11 +681,21 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "ghash" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" +dependencies = [ + "opaque-debug", + "polyval", +] + [[package]] name = "gimli" version = "0.26.1" @@ -535,7 +769,17 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" dependencies = [ - "hmac", + "hmac 0.12.1", +] + +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac 0.11.1", + "digest 0.9.0", ] [[package]] @@ -544,7 +788,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.3", ] [[package]] @@ -638,13 +882,22 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "instant" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -705,7 +958,7 @@ version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -735,7 +988,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "658646b21e0b72f7866c7038ab086d3d5e1cd6271f060fd37defb241949d0582" dependencies = [ - "digest", + "digest 0.10.3", ] [[package]] @@ -797,9 +1050,11 @@ dependencies = [ name = "nccd" version = "0.1.0" dependencies = [ + "async-session", "axum", "axum-extra", "axum-macros", + "bcrypt", "chrono", "color-eyre", "hyper", @@ -813,6 +1068,7 @@ dependencies = [ "tower-http", "tracing", "tracing-subscriber", + "ulid", ] [[package]] @@ -887,6 +1143,15 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + [[package]] name = "object" version = "0.29.0" @@ -902,6 +1167,12 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "owo-colors" version = "3.4.0" @@ -935,7 +1206,7 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "instant", "libc", "redox_syscall", @@ -949,7 +1220,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", @@ -1000,6 +1271,18 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "polyval" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.16" @@ -1241,9 +1524,22 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", - "digest", + "digest 0.10.3", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", ] [[package]] @@ -1252,9 +1548,9 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", - "digest", + "digest 0.10.3", ] [[package]] @@ -1349,7 +1645,7 @@ dependencies = [ "hashlink", "hex", "hkdf", - "hmac", + "hmac 0.12.1", "indexmap", "ipnetwork", "itoa", @@ -1366,7 +1662,7 @@ dependencies = [ "serde", "serde_json", "sha-1", - "sha2", + "sha2 0.10.2", "smallvec", "sqlformat", "sqlx-rt", @@ -1390,7 +1686,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "sha2", + "sha2 0.10.2", "sqlx-core", "sqlx-rt", "syn", @@ -1481,6 +1777,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "time" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217" +dependencies = [ + "itoa", + "libc", + "num_threads", + "time-macros", +] + +[[package]] +name = "time-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" + [[package]] name = "tinyvec" version = "1.6.0" @@ -1633,7 +1947,7 @@ version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "log", "pin-project-lite", "tracing-attributes", @@ -1712,6 +2026,16 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +[[package]] +name = "ulid" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be932d774bfad49722da2c4915ac7cc77b77dd223890739a0240de2b2a15957" +dependencies = [ + "rand", + "time 0.3.11", +] + [[package]] name = "unicase" version = "2.6.0" @@ -1754,6 +2078,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "untrusted" version = "0.7.1" @@ -1812,7 +2146,7 @@ version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] @@ -1963,3 +2297,9 @@ name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "zeroize" +version = "1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20b578acffd8516a6c3f2a1bdefc1ec37e547bb4e0fb8b6b01a4cafc886b4442" diff --git a/Cargo.toml b/Cargo.toml index 9a08b4a..9c656f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ build = "src/build.rs" [dependencies] axum = { version = "0.5.13", features = ["json", "tower-log"] } -axum-extra = { version = "0.3.6", features = ["spa"] } +axum-extra = { version = "0.3.6", features = ["spa", "cookie", "cookie-private"] } color-eyre = "0.6.2" hyper = { version = "0.14.20", features = ["full"] } serde = { version = "1.0.139", features = ["derive"] } @@ -22,6 +22,9 @@ tracing = "0.1.35" tracing-subscriber = { version = "0.3.14", features = ["env-filter"] } axum-macros = "0.2.3" chrono = "0.4.19" +ulid = "0.6.0" +async-session = "3.0.0" +bcrypt = "0.13.0" [dependencies.sqlx] version = "0.6" diff --git a/scss/style.scss b/scss/style.scss index 83485c7..ede6466 100644 --- a/scss/style.scss +++ b/scss/style.scss @@ -1,6 +1,6 @@ $color-bg: #282828; $color-fg: #ebdbb2; -$color-accent: #458588; +$color-accent: #d79921; $color-link: #458588; $color-danger: #cc241d; $font-family: monospace; @@ -19,3 +19,38 @@ a a:active, a:visited { margin: auto; width: 60%; } + +button { + border-radius: 8px; + background-color: $color-link; + border-color: $color-link; + border: none; + margin: 0.5rem; +} + +button.accent { + background-color: $color-accent; + border-color: $color-accent; +} + +// Forms +form { + width: 40%; +} + +label, +input { + display: inline-block; +} + +label { + width: 40%; + text-align: right; +} + +label+input { + width: 40% + + margin: 0 30% 0 4%; +} + diff --git a/src/config.rs b/src/config.rs index 9bacc6a..4ceba75 100644 --- a/src/config.rs +++ b/src/config.rs @@ -14,6 +14,7 @@ pub struct Config { #[derive(Deserialize)] pub struct ServerConfig { pub bind_addr: String, + pub admin_email: String } #[derive(Deserialize, Clone)] diff --git a/src/errors.rs b/src/errors.rs index 19e0a8a..23ad8fa 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -14,7 +14,11 @@ pub enum ServiceError { #[error("Not Found")] NotFound, #[error("Axum: {0}")] - Axum(#[from] axum::Error) + Axum(#[from] axum::Error), + #[error("SQL: {0}")] + Sql(#[from] sqlx::Error), + #[error("Bcrypt: {0}")] + Bcrypt(#[from] bcrypt::BcryptError), } pub type StringResult = Result; diff --git a/src/handlers/auth.rs b/src/handlers/auth.rs new file mode 100644 index 0000000..c4672aa --- /dev/null +++ b/src/handlers/auth.rs @@ -0,0 +1,79 @@ +use std::sync::Arc; + +use axum::{response::{IntoResponse, Html, Redirect}, Form, Extension}; +use axum_extra::extract::{PrivateCookieJar, cookie::Cookie}; +use serde::Deserialize; +use sqlx::{query, query_as}; +use tracing::debug; +use crate::{errors::ServiceError, State, models::DbUser}; +use chrono::prelude::*; + +#[derive(Deserialize, Debug)] +pub struct RegisterForm { + pub email: String, + pub prefname: String, + pub password: String, + #[serde(rename="password-confirm")] + pub password_confirm: String +} + +#[derive(Deserialize)] +pub struct LoginForm { + pub email: String, + pub password: String, +} + +pub async fn login() -> impl IntoResponse { + let mut buf = Vec::new(); + crate::templates::login_html(&mut buf).unwrap(); + + Html(buf) +} + +pub async fn login_post(Form(login): Form, state: Extension>, jar: PrivateCookieJar) -> Result<(PrivateCookieJar, Redirect), ServiceError> { + let mut conn = state.conn.acquire().await?; + + let user: DbUser = query_as("SELECT * FROM users WHERE email=$1").bind(login.email) + .fetch_one(&mut conn) + .await?; + + if bcrypt::verify(login.password, &user.pw_hash)? { + debug!("Logged in ID {} (email {})", user.id, user.email); + query("UPDATE users SET last_login=$1 WHERE id=$2").bind(Utc::now()).bind(user.id) + .execute(&mut conn) + .await?; + + let updated_jar = jar.add(Cookie::new("user-id", user.id.clone())); + } else { + + } + Ok((updated_jar, Redirect::to("/"))) +} + +pub async fn register() -> impl IntoResponse { + let mut buf = Vec::new(); + crate::templates::register_html(&mut buf).unwrap(); + + Html(buf) +} + +pub async fn register_post(Form(reg): Form, state: Extension>) -> impl IntoResponse { + if reg.password_confirm == reg.password { + let hash = match bcrypt::hash(reg.password, bcrypt::DEFAULT_COST) { + Ok(h) => h, + Err(e) => { + return Err(ServiceError::NotAuthorized); + } + }; + + let mut conn = state.conn.acquire().await?; + let ulid = ulid::Ulid::new(); + + query("INSERT INTO users (id, email, pref_name, pw_hash, last_login) VALUES ($1, $2, $3, $4, $5)").bind(ulid.to_string()).bind(reg.email.clone()).bind(reg.prefname).bind(hash).bind(Utc::now()) + .execute(&mut conn) + .await?; + + } + + Ok(Redirect::to("/dash/auth/login")) +} diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs new file mode 100644 index 0000000..4076e68 --- /dev/null +++ b/src/handlers/mod.rs @@ -0,0 +1,16 @@ +use axum::{Router, routing::get}; + +mod auth; + +pub async fn gen_routers() -> Router { + + Router::new() + .nest("/auth", auth_routes().await) +} + +async fn auth_routes() -> Router { + + Router::new() + .route("/login", get(auth::login).post(auth::login_post)) + .route("/register", get(auth::register).post(auth::register_post)) +} diff --git a/src/main.rs b/src/main.rs index c4a298f..ed943c7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,7 @@ mod config; mod errors; +mod handlers; +mod models; use std::{net::SocketAddr, str::FromStr, sync::Arc, time::Duration}; @@ -50,6 +52,7 @@ async fn main() { let app = Router::new() .route("/health", get(health_check)) .route("/", get(index)) + .nest("/dash", handlers::gen_routers().await) .route("/static/:name", get(statics)) .layer( ServiceBuilder::new() diff --git a/src/models.rs b/src/models.rs new file mode 100644 index 0000000..b367f4f --- /dev/null +++ b/src/models.rs @@ -0,0 +1,12 @@ +use sqlx::FromRow; + + + +#[derive(Debug, FromRow)] +pub struct DbUser { + pub id: String, + pub email: String, + pub pref_name: String, + pub pw_hash: String, + pub last_login: chrono::NaiveDateTime +} diff --git a/templates/footer.rs.html b/templates/footer.rs.html new file mode 100644 index 0000000..41c4d4e --- /dev/null +++ b/templates/footer.rs.html @@ -0,0 +1,7 @@ + +@() + + + + + diff --git a/templates/header.rs.html b/templates/header.rs.html new file mode 100644 index 0000000..9384bcb --- /dev/null +++ b/templates/header.rs.html @@ -0,0 +1,14 @@ +@use super::statics::style_css; +@() + + + + NCCd Dashboard + + + + + + + +
diff --git a/templates/index.rs.html b/templates/index.rs.html index 2971d13..4fb701c 100644 --- a/templates/index.rs.html +++ b/templates/index.rs.html @@ -1,21 +1,8 @@ -@use super::statics::style_css; +@use super::{header_html, footer_html}; @() - - - - NCCd Dashboard - - - - - - - -
+@:header_html()

NCCd (Network Communications Control Daemon)

-

Please Log in

- - - +

Please Log in

+@:footer_html() diff --git a/templates/login.rs.html b/templates/login.rs.html new file mode 100644 index 0000000..122e2b8 --- /dev/null +++ b/templates/login.rs.html @@ -0,0 +1,22 @@ +@use super::{header_html, footer_html}; + +@() + +@:header_html() +

NCCd Login

+
+
+ + +
+
+
+ + +
+
+ + + +Or try creating an account +@:footer_html() diff --git a/templates/register.rs.html b/templates/register.rs.html new file mode 100644 index 0000000..5c2e3f2 --- /dev/null +++ b/templates/register.rs.html @@ -0,0 +1,27 @@ +@use super::{header_html, footer_html}; + +@() + +@:header_html() +

Create your NCCd Account

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ Submit +
+Or try logging in +@:footer_html() -- cgit v1.2.3