aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCara Salter <cara@devcara.com>2022-07-19 19:49:39 -0400
committerCara Salter <cara@devcara.com>2022-07-19 19:49:39 -0400
commitc742b752140ab0eee6e353c779bd897042ba6739 (patch)
tree58953fdcaedb7e6c458a29dd980b8f97fb1af2a7
parent1bd04149f8f6133b817a37a37a91397750c76c1b (diff)
downloadnccd-c742b752140ab0eee6e353c779bd897042ba6739.tar.gz
nccd-c742b752140ab0eee6e353c779bd897042ba6739.zip
Big login system
Still needs cookies, but those are coming! (and should be set anyways!)
-rw-r--r--Cargo.lock384
-rw-r--r--Cargo.toml5
-rw-r--r--scss/style.scss37
-rw-r--r--src/config.rs1
-rw-r--r--src/errors.rs6
-rw-r--r--src/handlers/auth.rs79
-rw-r--r--src/handlers/mod.rs16
-rw-r--r--src/main.rs3
-rw-r--r--src/models.rs12
-rw-r--r--templates/footer.rs.html7
-rw-r--r--templates/header.rs.html14
-rw-r--r--templates/index.rs.html21
-rw-r--r--templates/login.rs.html22
-rw-r--r--templates/register.rs.html27
14 files changed, 592 insertions, 42 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 6d31ed5..dfe189f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -18,6 +18,41 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -38,6 +73,54 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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",
@@ -161,12 +245,57 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -176,6 +305,16 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -207,6 +346,12 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
@@ -220,11 +365,31 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -252,6 +417,27 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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",
]
@@ -306,12 +492,50 @@ dependencies = [
]
[[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,12 +681,22 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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]]
@@ -639,12 +883,21 @@ dependencies = [
]
[[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]]
@@ -888,6 +1144,15 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -903,6 +1168,12 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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",
@@ -1001,6 +1272,18 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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",
@@ -1482,6 +1778,24 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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",
@@ -1713,6 +2027,16 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1755,6 +2079,16 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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<T = String> = Result<T, ServiceError>;
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<LoginForm>, state: Extension<Arc<State>>, 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<RegisterForm>, state: Extension<Arc<State>>) -> 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 @@
+
+@()
+
+
+ </div>
+ </body>
+</html>
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;
+@()
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <title>NCCd Dashboard</title>
+ <link rel="stylesheet" href="/static/@style_css.name"/>
+
+ <meta name="viewport" content="width=device-width,initial-scale=1.0">
+ </head>
+
+ <body>
+
+ <div class="container">
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};
@()
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <title>NCCd Dashboard</title>
- <link rel="stylesheet" href="/static/@style_css.name"/>
-
- <meta name="viewport" content="width=device-width,initial-scale=1.0">
- </head>
-
- <body>
-
- <div class="container">
+@:header_html()
<h1>NCCd (Network Communications Control Daemon)</h1>
- <h3>Please <a href="/auth/login">Log in</a></h3>
-
- </body>
-</html>
+ <h3>Please <a href="/dash/auth/login">Log in</a></h3>
+@: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()
+<h1>NCCd Login</h1>
+<form method="POST">
+ <div>
+ <label for="username">Email</label>
+ <input type="text" name="email">
+ </div>
+ <br/>
+ <div>
+ <label for="password">Password</label>
+ <input type="password" name="password">
+ </div>
+ <div>
+ <button type="submit" class="accent">Submit</button>
+</form>
+
+Or try <a href="/dash/auth/register">creating an account</a>
+@: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()
+<h1>Create your NCCd Account</h1>
+<form method="POST" action="/dash/auth/register">
+ <div>
+ <label for="email">Email</label>
+ <input type="text" id="email" name="email">
+ </div>
+ <div>
+ <label for="prefname">Preferred name</label>
+ <input type="text" id="prefname" name="prefname">
+ </div>
+ <div>
+ <label for="password">Password</label>
+ <input type="password" id="password" name="password">
+ </div>
+ <div>
+ <label for="password-confirm">Confirm password</label>
+ <input type="password" id="password-confirm" name="password-confirm">
+ </div>
+ <input type="submit" class="accent">Submit</input>
+</form>
+Or try <a href="/dash/auth/login">logging in</a>
+@:footer_html()