almost works, still need to impl auth
This commit is contained in:
parent
d4a684de29
commit
57eb4001ee
12 changed files with 266 additions and 309 deletions
321
Cargo.lock
generated
321
Cargo.lock
generated
|
@ -158,8 +158,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a41603f7cdbf5ac4af60760f17253eb6adf6ec5b6f14a7ed830cf687d375f163"
|
checksum = "a41603f7cdbf5ac4af60760f17253eb6adf6ec5b6f14a7ed830cf687d375f163"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"askama",
|
"askama",
|
||||||
"axum-core 0.4.1",
|
"axum-core",
|
||||||
"http 1.0.0",
|
"http",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -175,7 +175,7 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"serde",
|
"serde",
|
||||||
"syn 2.0.39",
|
"syn 2.0.41",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -231,7 +231,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.41",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -265,38 +265,6 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "axum"
|
|
||||||
version = "0.6.20"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
|
|
||||||
dependencies = [
|
|
||||||
"async-trait",
|
|
||||||
"axum-core 0.3.4",
|
|
||||||
"bitflags 1.3.2",
|
|
||||||
"bytes",
|
|
||||||
"futures-util",
|
|
||||||
"http 0.2.11",
|
|
||||||
"http-body 0.4.6",
|
|
||||||
"hyper 0.14.27",
|
|
||||||
"itoa",
|
|
||||||
"matchit",
|
|
||||||
"memchr",
|
|
||||||
"mime",
|
|
||||||
"percent-encoding",
|
|
||||||
"pin-project-lite",
|
|
||||||
"rustversion",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"serde_path_to_error",
|
|
||||||
"serde_urlencoded",
|
|
||||||
"sync_wrapper",
|
|
||||||
"tokio",
|
|
||||||
"tower",
|
|
||||||
"tower-layer",
|
|
||||||
"tower-service",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "axum"
|
name = "axum"
|
||||||
version = "0.7.2"
|
version = "0.7.2"
|
||||||
|
@ -304,14 +272,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "202651474fe73c62d9e0a56c6133f7a0ff1dc1c8cf7a5b03381af2a26553ac9d"
|
checksum = "202651474fe73c62d9e0a56c6133f7a0ff1dc1c8cf7a5b03381af2a26553ac9d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum-core 0.4.1",
|
"axum-core",
|
||||||
"axum-macros",
|
"axum-macros",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http 1.0.0",
|
"http",
|
||||||
"http-body 1.0.0",
|
"http-body",
|
||||||
"http-body-util",
|
"http-body-util",
|
||||||
"hyper 1.0.1",
|
"hyper",
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
"itoa",
|
"itoa",
|
||||||
"matchit",
|
"matchit",
|
||||||
|
@ -331,23 +299,6 @@ dependencies = [
|
||||||
"tower-service",
|
"tower-service",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "axum-core"
|
|
||||||
version = "0.3.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c"
|
|
||||||
dependencies = [
|
|
||||||
"async-trait",
|
|
||||||
"bytes",
|
|
||||||
"futures-util",
|
|
||||||
"http 0.2.11",
|
|
||||||
"http-body 0.4.6",
|
|
||||||
"mime",
|
|
||||||
"rustversion",
|
|
||||||
"tower-layer",
|
|
||||||
"tower-service",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "axum-core"
|
name = "axum-core"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
@ -357,8 +308,8 @@ dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http 1.0.0",
|
"http",
|
||||||
"http-body 1.0.0",
|
"http-body",
|
||||||
"http-body-util",
|
"http-body-util",
|
||||||
"mime",
|
"mime",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
@ -375,8 +326,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "40f7051fdc094b6e5ea06cab9bca4b198c54dee4472a9419155f0ff19f19901e"
|
checksum = "40f7051fdc094b6e5ea06cab9bca4b198c54dee4472a9419155f0ff19f19901e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum-core 0.4.1",
|
"axum-core",
|
||||||
"http 1.0.0",
|
"http",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -386,7 +337,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "61b018d073eea48729e2309c8ecd7198e1eea90e132d99a5e1cc7e952053c8d6"
|
checksum = "61b018d073eea48729e2309c8ecd7198e1eea90e132d99a5e1cc7e952053c8d6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum 0.7.2",
|
"axum",
|
||||||
"ring",
|
"ring",
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
@ -407,24 +358,34 @@ dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.41",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "axum-test"
|
name = "axum-test"
|
||||||
version = "9.1.1"
|
version = "14.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8822bb73c863cdc96a4476fdae6443495c9c312f9f659720aa4ea59d76074577"
|
checksum = "56ac99db40006a1a3fffeb381f2a78cb341dbc99d07b561e8bd119e22a2b1b0f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"async-trait",
|
||||||
"auto-future",
|
"auto-future",
|
||||||
"axum 0.6.20",
|
"axum",
|
||||||
"cookie 0.17.0",
|
"bytes",
|
||||||
"hyper 0.14.27",
|
"cookie",
|
||||||
"portpicker",
|
"http",
|
||||||
|
"http-body-util",
|
||||||
|
"hyper",
|
||||||
|
"hyper-util",
|
||||||
|
"pretty_assertions",
|
||||||
|
"reserve-port",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"serde_urlencoded",
|
||||||
|
"smallvec",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tower",
|
||||||
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -621,7 +582,7 @@ dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.41",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -638,9 +599,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "const-oid"
|
name = "const-oid"
|
||||||
version = "0.9.5"
|
version = "0.9.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"
|
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "constant_time_eq"
|
name = "constant_time_eq"
|
||||||
|
@ -648,16 +609,6 @@ version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cookie"
|
|
||||||
version = "0.17.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7efb37c3e1ccb1ff97164ad95ac1606e8ccd35b3fa0a7d99a304c7f4a428cc24"
|
|
||||||
dependencies = [
|
|
||||||
"time 0.3.30",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cookie"
|
name = "cookie"
|
||||||
version = "0.18.0"
|
version = "0.18.0"
|
||||||
|
@ -701,9 +652,9 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-queue"
|
name = "crossbeam-queue"
|
||||||
version = "0.3.8"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add"
|
checksum = "b9bcf5bdbfdd6030fb4a1c497b5d5fc5921aa2f60d359a17e249c0e6df3de153"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
|
@ -711,9 +662,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.16"
|
version = "0.8.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
]
|
]
|
||||||
|
@ -769,6 +720,12 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diff"
|
||||||
|
version = "0.1.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
|
@ -942,7 +899,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.41",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1012,7 +969,7 @@ dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http 1.0.0",
|
"http",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"slab",
|
"slab",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -1062,9 +1019,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hkdf"
|
name = "hkdf"
|
||||||
version = "0.12.3"
|
version = "0.12.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
|
checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hmac 0.12.1",
|
"hmac 0.12.1",
|
||||||
]
|
]
|
||||||
|
@ -1090,22 +1047,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "home"
|
name = "home"
|
||||||
version = "0.5.5"
|
version = "0.5.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
|
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "http"
|
|
||||||
version = "0.2.11"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"fnv",
|
|
||||||
"itoa",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1119,17 +1065,6 @@ dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "http-body"
|
|
||||||
version = "0.4.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"http 0.2.11",
|
|
||||||
"pin-project-lite",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http-body"
|
name = "http-body"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -1137,7 +1072,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
|
checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"http 1.0.0",
|
"http",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1148,16 +1083,16 @@ checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http 1.0.0",
|
"http",
|
||||||
"http-body 1.0.0",
|
"http-body",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http-range-header"
|
name = "http-range-header"
|
||||||
version = "0.3.1"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f"
|
checksum = "3ce4ef31cda248bbdb6e6820603b82dfcd9e833db65a43e997a0ccec777d11fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httparse"
|
name = "httparse"
|
||||||
|
@ -1180,29 +1115,6 @@ dependencies = [
|
||||||
"libm",
|
"libm",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hyper"
|
|
||||||
version = "0.14.27"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"futures-channel",
|
|
||||||
"futures-core",
|
|
||||||
"futures-util",
|
|
||||||
"http 0.2.11",
|
|
||||||
"http-body 0.4.6",
|
|
||||||
"httparse",
|
|
||||||
"httpdate",
|
|
||||||
"itoa",
|
|
||||||
"pin-project-lite",
|
|
||||||
"socket2 0.4.10",
|
|
||||||
"tokio",
|
|
||||||
"tower-service",
|
|
||||||
"tracing",
|
|
||||||
"want",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -1213,13 +1125,14 @@ dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"h2",
|
"h2",
|
||||||
"http 1.0.0",
|
"http",
|
||||||
"http-body 1.0.0",
|
"http-body",
|
||||||
"httparse",
|
"httparse",
|
||||||
"httpdate",
|
"httpdate",
|
||||||
"itoa",
|
"itoa",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"want",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1231,11 +1144,11 @@ dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http 1.0.0",
|
"http",
|
||||||
"http-body 1.0.0",
|
"http-body",
|
||||||
"hyper 1.0.1",
|
"hyper",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2 0.5.5",
|
"socket2",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower",
|
"tower",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
|
@ -1576,7 +1489,7 @@ name = "optional_optional_user"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.41",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1657,7 +1570,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.41",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1699,15 +1612,6 @@ version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "portpicker"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "be97d76faf1bfab666e1375477b23fde79eccf0276e9b63b92a39d676a889ba9"
|
|
||||||
dependencies = [
|
|
||||||
"rand",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "powerfmt"
|
name = "powerfmt"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -1720,6 +1624,16 @@ version = "0.2.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pretty_assertions"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66"
|
||||||
|
dependencies = [
|
||||||
|
"diff",
|
||||||
|
"yansi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.70"
|
version = "1.0.70"
|
||||||
|
@ -1831,6 +1745,16 @@ version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "reserve-port"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3969e7fe15c6c1532ba1a761628298e870bbd18c252fd41a58445f6091c372a0"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
version = "0.17.7"
|
version = "0.17.7"
|
||||||
|
@ -1941,7 +1865,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.41",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2076,16 +2000,6 @@ version = "1.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
|
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "socket2"
|
|
||||||
version = "0.4.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.5.5"
|
version = "0.5.5"
|
||||||
|
@ -2373,9 +2287,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.39"
|
version = "2.0.41"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
|
checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -2403,22 +2317,22 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.50"
|
version = "1.0.51"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
|
checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.50"
|
version = "1.0.51"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
|
checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.41",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2500,7 +2414,7 @@ dependencies = [
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"socket2 0.5.5",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"tracing",
|
"tracing",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
|
@ -2514,7 +2428,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.41",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2576,10 +2490,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4fd0118512cf0b3768f7fcccf0bef1ae41d68f2b45edc1e77432b36c97c56c6d"
|
checksum = "4fd0118512cf0b3768f7fcccf0bef1ae41d68f2b45edc1e77432b36c97c56c6d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum-core 0.4.1",
|
"axum-core",
|
||||||
"cookie 0.18.0",
|
"cookie",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http 1.0.0",
|
"http",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
|
@ -2588,16 +2502,16 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-http"
|
name = "tower-http"
|
||||||
version = "0.4.4"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140"
|
checksum = "09e12e6351354851911bdf8c2b8f2ab15050c567d70a8b9a37ae7b8301a4080d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.4.1",
|
"bitflags 2.4.1",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-core",
|
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http 0.2.11",
|
"http",
|
||||||
"http-body 0.4.6",
|
"http-body",
|
||||||
|
"http-body-util",
|
||||||
"http-range-header",
|
"http-range-header",
|
||||||
"httpdate",
|
"httpdate",
|
||||||
"mime",
|
"mime",
|
||||||
|
@ -2641,9 +2555,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b1d733b3ae4a6a4cb80cd585e87ffe1a1a7011174581785039c83c4cd63ee61c"
|
checksum = "b1d733b3ae4a6a4cb80cd585e87ffe1a1a7011174581785039c83c4cd63ee61c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum-core 0.4.1",
|
"axum-core",
|
||||||
"futures",
|
"futures",
|
||||||
"http 1.0.0",
|
"http",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -2702,7 +2616,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.41",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2903,7 +2817,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.41",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2925,7 +2839,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.41",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
@ -2945,13 +2859,14 @@ dependencies = [
|
||||||
"askama_axum",
|
"askama_axum",
|
||||||
"async-session",
|
"async-session",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum 0.7.2",
|
"axum",
|
||||||
"axum-htmx",
|
"axum-htmx",
|
||||||
"axum-login",
|
"axum-login",
|
||||||
"axum-macros",
|
"axum-macros",
|
||||||
"axum-test",
|
"axum-test",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
|
"http",
|
||||||
"julid-rs",
|
"julid-rs",
|
||||||
"justerror",
|
"justerror",
|
||||||
"optional_optional_user",
|
"optional_optional_user",
|
||||||
|
@ -3144,23 +3059,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "yansi"
|
||||||
version = "0.7.30"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "306dca4455518f1f31635ec308b6b3e4eb1b11758cefafc782827d0aa7acb5c7"
|
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy-derive",
|
"zerocopy-derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy-derive"
|
name = "zerocopy-derive"
|
||||||
version = "0.7.30"
|
version = "0.7.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "be912bf68235a88fbefd1b73415cb218405958d1655b2ece9035a19920bdf6ba"
|
checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.41",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -20,6 +20,7 @@ axum-login = "0.10"
|
||||||
axum-macros = "0.4"
|
axum-macros = "0.4"
|
||||||
chrono = { version = "0.4", default-features = false, features = ["std", "clock"] }
|
chrono = { version = "0.4", default-features = false, features = ["std", "clock"] }
|
||||||
clap = { version = "4", features = ["derive", "env", "unicode", "suggestions", "usage"] }
|
clap = { version = "4", features = ["derive", "env", "unicode", "suggestions", "usage"] }
|
||||||
|
http = "1.0.0"
|
||||||
julid-rs = "1"
|
julid-rs = "1"
|
||||||
justerror = "1"
|
justerror = "1"
|
||||||
password-hash = { version = "0.5", features = ["std", "getrandom"] }
|
password-hash = { version = "0.5", features = ["std", "getrandom"] }
|
||||||
|
@ -33,13 +34,13 @@ tokio = { version = "1", features = ["full", "tracing"], default-features = fals
|
||||||
tokio-retry = "0.3"
|
tokio-retry = "0.3"
|
||||||
tokio-stream = "0.1"
|
tokio-stream = "0.1"
|
||||||
tower = { version = "0.4", features = ["util", "timeout"], default-features = false }
|
tower = { version = "0.4", features = ["util", "timeout"], default-features = false }
|
||||||
tower-http = { version = "0.4", features = ["add-extension", "trace", "tracing", "fs"], default-features = false }
|
tower-http = { version = "0.5", features = ["add-extension", "trace", "tracing", "fs"], default-features = false }
|
||||||
tower-sessions = { version = "0.7", default-features = false, features = ["sqlite-store"] }
|
tower-sessions = { version = "0.7", default-features = false, features = ["sqlite-store"] }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||||
unicode-segmentation = "1"
|
unicode-segmentation = "1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
axum-test = "9"
|
axum-test = "14"
|
||||||
serde_test = "1"
|
serde_test = "1"
|
||||||
|
|
||||||
|
|
71
src/auth.rs
Normal file
71
src/auth.rs
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
use axum_login::{AuthnBackend, UserId};
|
||||||
|
|
||||||
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
|
use tower_sessions::{
|
||||||
|
cookie::time::Duration, Expiry, SessionManagerLayer,
|
||||||
|
SqliteStore,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::User;
|
||||||
|
|
||||||
|
const SESSION_TTL: Duration = Duration::new((365.2422 * 24. * 3600.0) as i64, 0);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct AuthStore(SqlitePool);
|
||||||
|
|
||||||
|
pub type AuthSession = axum_login::AuthSession<AuthStore>;
|
||||||
|
|
||||||
|
impl AuthStore {
|
||||||
|
pub fn new(pool: SqlitePool) -> Self {
|
||||||
|
AuthStore(pool)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::DerefMut for AuthStore {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Deref for AuthStore {
|
||||||
|
type Target = SqlitePool;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl AuthnBackend for AuthStore {
|
||||||
|
type User = User;
|
||||||
|
|
||||||
|
type Credentials = String;
|
||||||
|
|
||||||
|
type Error = sqlx::Error;
|
||||||
|
|
||||||
|
async fn authenticate(
|
||||||
|
&self,
|
||||||
|
_creds: Self::Credentials,
|
||||||
|
) -> Result<Option<Self::User>, Self::Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_user(&self, _user_id: &UserId<Self>) -> Result<Option<Self::User>, Self::Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn session_layer(pool: SqlitePool) -> SessionManagerLayer<SqliteStore> {
|
||||||
|
let store = SqliteStore::new(pool);
|
||||||
|
store
|
||||||
|
.migrate()
|
||||||
|
.await
|
||||||
|
.expect("Calling `migrate()` should be reliable, is the DB gone?");
|
||||||
|
|
||||||
|
SessionManagerLayer::new(store)
|
||||||
|
.with_secure(true)
|
||||||
|
.with_expiry(Expiry::OnInactivity(SESSION_TTL))
|
||||||
|
}
|
34
src/db.rs
34
src/db.rs
|
@ -1,22 +1,14 @@
|
||||||
use async_session::SessionStore;
|
use std::time::Duration;
|
||||||
use axum_login::{AuthManagerLayer, AuthManagerLayerBuilder, AuthSession, AuthUser, AuthnBackend};
|
|
||||||
use julid::Julid;
|
|
||||||
use sqlx::{
|
use sqlx::{
|
||||||
migrate::Migrator,
|
migrate::Migrator,
|
||||||
sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions},
|
sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions},
|
||||||
SqlitePool,
|
SqlitePool,
|
||||||
};
|
};
|
||||||
use tower_sessions::{
|
|
||||||
cookie::time::Duration, session_store::ExpiredDeletion, Expiry, Session, SessionManagerLayer,
|
|
||||||
SqliteStore,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::User;
|
|
||||||
|
|
||||||
const MAX_CONNS: u32 = 200;
|
const MAX_CONNS: u32 = 200;
|
||||||
const MIN_CONNS: u32 = 5;
|
const MIN_CONNS: u32 = 5;
|
||||||
const TIMEOUT: u64 = 11;
|
const TIMEOUT: u64 = 11;
|
||||||
const SESSION_TTL: Duration = Duration::new((365.2422 * 24. * 3600.0) as i64, 0);
|
|
||||||
|
|
||||||
pub fn get_db_pool() -> SqlitePool {
|
pub fn get_db_pool() -> SqlitePool {
|
||||||
let db_filename = {
|
let db_filename = {
|
||||||
|
@ -48,8 +40,7 @@ pub fn get_db_pool() -> SqlitePool {
|
||||||
.journal_mode(SqliteJournalMode::Wal)
|
.journal_mode(SqliteJournalMode::Wal)
|
||||||
.synchronous(sqlx::sqlite::SqliteSynchronous::Normal)
|
.synchronous(sqlx::sqlite::SqliteSynchronous::Normal)
|
||||||
.filename(&db_filename)
|
.filename(&db_filename)
|
||||||
// need to build this out of band and put it in the project root; see instructions at
|
// be sure to have run `make` so that the libjulid extension is built
|
||||||
// https://gitlab.com/nebkor/julid
|
|
||||||
.extension("./libjulid")
|
.extension("./libjulid")
|
||||||
.busy_timeout(Duration::from_secs(TIMEOUT))
|
.busy_timeout(Duration::from_secs(TIMEOUT))
|
||||||
.create_if_missing(true);
|
.create_if_missing(true);
|
||||||
|
@ -86,25 +77,6 @@ pub fn get_db_pool() -> SqlitePool {
|
||||||
pool
|
pool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn session_layer(pool: SqlitePool) -> SessionManagerLayer<SqliteStore> {
|
|
||||||
let store = SqliteStore::new(pool);
|
|
||||||
store
|
|
||||||
.migrate()
|
|
||||||
.await
|
|
||||||
.expect("Calling `migrate()` should be reliable, is the DB gone?");
|
|
||||||
|
|
||||||
SessionManagerLayer::new(store)
|
|
||||||
.with_secure(true)
|
|
||||||
.with_expiry(Expiry::OnInactivity(SESSION_TTL.into()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn auth_layer(
|
|
||||||
pool: SqlitePool,
|
|
||||||
secret: &[u8],
|
|
||||||
) -> AuthManagerLayer<SqliteStore, SessionManagerLayer<SqliteStore>> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
//-************************************************************************
|
//-************************************************************************
|
||||||
// Tests for `db` module.
|
// Tests for `db` module.
|
||||||
//-************************************************************************
|
//-************************************************************************
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
use axum::response::{IntoResponse, Redirect};
|
use axum::response::{IntoResponse, Redirect};
|
||||||
|
|
||||||
use crate::{AuthContext, MainPage};
|
use crate::{AuthSession, MainPage};
|
||||||
|
|
||||||
pub async fn handle_slash_redir() -> impl IntoResponse {
|
pub async fn handle_slash_redir() -> impl IntoResponse {
|
||||||
Redirect::to("/")
|
Redirect::to("/")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_slash(auth: AuthContext) -> impl IntoResponse {
|
pub async fn handle_slash(auth: AuthSession) -> impl IntoResponse {
|
||||||
if let Some(ref user) = auth.current_user {
|
if let Some(ref user) = auth.user {
|
||||||
let name = &user.username;
|
let name = &user.username;
|
||||||
tracing::debug!("Logged in as: {name}");
|
tracing::debug!("Logged in as: {name}");
|
||||||
} else {
|
} else {
|
||||||
tracing::debug!("Not logged in.");
|
tracing::debug!("Not logged in.");
|
||||||
}
|
}
|
||||||
MainPage {
|
MainPage { user: auth.user }
|
||||||
user: auth.current_user,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
32
src/lib.rs
32
src/lib.rs
|
@ -1,4 +1,4 @@
|
||||||
use axum::routing::IntoMakeService;
|
use axum::{error_handling::HandleErrorLayer, routing::IntoMakeService, BoxError};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate justerror;
|
extern crate justerror;
|
||||||
|
@ -10,12 +10,14 @@ pub mod test_utils;
|
||||||
/// app
|
/// app
|
||||||
pub use db::get_db_pool;
|
pub use db::get_db_pool;
|
||||||
pub mod import_utils;
|
pub mod import_utils;
|
||||||
|
|
||||||
pub use users::User;
|
pub use users::User;
|
||||||
pub use watches::{ShowKind, Watch, WatchQuest};
|
pub use watches::{ShowKind, Watch, WatchQuest};
|
||||||
|
|
||||||
pub type WWRouter = axum::Router<SqlitePool>;
|
pub type WWRouter = axum::Router<SqlitePool>;
|
||||||
|
|
||||||
// everything else is private to the crate
|
// everything else is private to the crate
|
||||||
|
mod auth;
|
||||||
mod db;
|
mod db;
|
||||||
mod generic_handlers;
|
mod generic_handlers;
|
||||||
mod login;
|
mod login;
|
||||||
|
@ -26,17 +28,16 @@ mod util;
|
||||||
mod watches;
|
mod watches;
|
||||||
|
|
||||||
// things we want in the crate namespace
|
// things we want in the crate namespace
|
||||||
|
use auth::AuthSession;
|
||||||
use optional_optional_user::OptionalOptionalUser;
|
use optional_optional_user::OptionalOptionalUser;
|
||||||
use templates::*;
|
use templates::*;
|
||||||
use watches::templates::*;
|
use watches::templates::*;
|
||||||
|
|
||||||
type AuthContext =
|
|
||||||
axum_login::extractors::AuthContext<julid::Julid, User, axum_login::SqliteStore<User>>;
|
|
||||||
|
|
||||||
/// Returns the router to be used as a service or test object, you do you.
|
/// Returns the router to be used as a service or test object, you do you.
|
||||||
pub async fn app(db_pool: sqlx::SqlitePool, secret: &[u8]) -> IntoMakeService<axum::Router> {
|
pub async fn app(db_pool: sqlx::SqlitePool) -> IntoMakeService<axum::Router> {
|
||||||
use axum::{middleware, routing::get};
|
|
||||||
// don't bother bringing handlers into the whole crate namespace
|
// don't bother bringing handlers into the whole crate namespace
|
||||||
|
use auth::*;
|
||||||
|
use axum::{middleware, routing::get};
|
||||||
use generic_handlers::{handle_slash, handle_slash_redir};
|
use generic_handlers::{handle_slash, handle_slash_redir};
|
||||||
use login::{get_login, get_logout, post_login, post_logout};
|
use login::{get_login, get_logout, post_login, post_logout};
|
||||||
use signup::{get_create_user, get_signup_success, post_create_user};
|
use signup::{get_create_user, get_signup_success, post_create_user};
|
||||||
|
@ -46,23 +47,25 @@ pub async fn app(db_pool: sqlx::SqlitePool, secret: &[u8]) -> IntoMakeService<ax
|
||||||
post_add_watch_quest,
|
post_add_watch_quest,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (session_layer, auth_layer) = {
|
let auth_layer = {
|
||||||
let session_layer = db::session_layer(db_pool.clone(), secret).await;
|
let sessions = session_layer(db_pool.clone()).await;
|
||||||
let auth_layer = db::auth_layer(db_pool.clone(), secret).await;
|
let store = AuthStore::new(db_pool.clone());
|
||||||
(session_layer, auth_layer)
|
tower::ServiceBuilder::new()
|
||||||
|
.layer(HandleErrorLayer::new(|_: BoxError| async {
|
||||||
|
http::StatusCode::BAD_REQUEST
|
||||||
|
}))
|
||||||
|
.layer(axum_login::AuthManagerLayerBuilder::new(store, sessions).build())
|
||||||
};
|
};
|
||||||
|
|
||||||
let css_dir = std::env::current_dir()
|
let css_dir = std::env::current_dir()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.join("templates")
|
.join("templates")
|
||||||
.join("css");
|
.join("css");
|
||||||
|
let css_svc = ServeDir::new(css_dir.as_path());
|
||||||
|
|
||||||
axum::Router::new()
|
axum::Router::new()
|
||||||
.route("/", get(handle_slash).post(handle_slash))
|
.route("/", get(handle_slash).post(handle_slash))
|
||||||
.nest_service(
|
.nest_service("/css", css_svc)
|
||||||
"/css",
|
|
||||||
ServeDir::new(css_dir.as_path()).append_index_html_on_directories(false),
|
|
||||||
)
|
|
||||||
.route("/signup", get(get_create_user).post(post_create_user))
|
.route("/signup", get(get_create_user).post(post_create_user))
|
||||||
.route("/signup_success/:id", get(get_signup_success))
|
.route("/signup_success/:id", get(get_signup_success))
|
||||||
.route("/login", get(get_login).post(post_login))
|
.route("/login", get(get_login).post(post_login))
|
||||||
|
@ -82,7 +85,6 @@ pub async fn app(db_pool: sqlx::SqlitePool, secret: &[u8]) -> IntoMakeService<ax
|
||||||
users::handle_update_last_seen,
|
users::handle_update_last_seen,
|
||||||
))
|
))
|
||||||
.layer(auth_layer)
|
.layer(auth_layer)
|
||||||
.layer(session_layer)
|
|
||||||
.with_state(db_pool)
|
.with_state(db_pool)
|
||||||
.into_make_service()
|
.into_make_service()
|
||||||
}
|
}
|
||||||
|
|
27
src/login.rs
27
src/login.rs
|
@ -11,7 +11,7 @@ use axum::{
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use crate::{AuthContext, LoginPage, LogoutPage, LogoutSuccessPage, User};
|
use crate::{AuthSession, LoginPage, LogoutPage, LogoutSuccessPage, User};
|
||||||
|
|
||||||
//-************************************************************************
|
//-************************************************************************
|
||||||
// Constants
|
// Constants
|
||||||
|
@ -41,6 +41,7 @@ impl IntoResponse for LoginError {
|
||||||
)
|
)
|
||||||
.into_response(),
|
.into_response(),
|
||||||
LoginErrorKind::Unknown => (StatusCode::OK, "Not successful.").into_response(),
|
LoginErrorKind::Unknown => (StatusCode::OK, "Not successful.").into_response(),
|
||||||
|
// we don't say it's a bad password, we just silently fail
|
||||||
_ => (StatusCode::OK, format!("{self}")).into_response(),
|
_ => (StatusCode::OK, format!("{self}")).into_response(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +61,7 @@ pub struct LoginPostForm {
|
||||||
/// Handle login queries
|
/// Handle login queries
|
||||||
#[axum::debug_handler]
|
#[axum::debug_handler]
|
||||||
pub async fn post_login(
|
pub async fn post_login(
|
||||||
mut auth: AuthContext,
|
mut auth: AuthSession,
|
||||||
State(pool): State<SqlitePool>,
|
State(pool): State<SqlitePool>,
|
||||||
Form(login): Form<LoginPostForm>,
|
Form(login): Form<LoginPostForm>,
|
||||||
) -> Result<impl IntoResponse, LoginError> {
|
) -> Result<impl IntoResponse, LoginError> {
|
||||||
|
@ -98,11 +99,15 @@ pub async fn get_logout() -> impl IntoResponse {
|
||||||
LogoutPage
|
LogoutPage
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn post_logout(mut auth: AuthContext) -> impl IntoResponse {
|
pub async fn post_logout(mut auth: AuthSession) -> impl IntoResponse {
|
||||||
if auth.current_user.is_some() {
|
match auth.logout() {
|
||||||
auth.logout().await;
|
Ok(_) => LogoutSuccessPage.into_response(),
|
||||||
|
Err(e) => {
|
||||||
|
tracing::debug!("{e}");
|
||||||
|
let e: LoginError = LoginErrorKind::Internal.into();
|
||||||
|
e.into_response()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LogoutSuccessPage
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-************************************************************************
|
//-************************************************************************
|
||||||
|
@ -131,7 +136,7 @@ mod test {
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let s = server_with_pool(&db).await;
|
let s = server_with_pool(&db).await;
|
||||||
let resp = s.get("/login").await;
|
let resp = s.get("/login").await;
|
||||||
let body = std::str::from_utf8(resp.bytes()).unwrap().to_string();
|
let body = std::str::from_utf8(resp.as_bytes()).unwrap().to_string();
|
||||||
assert_eq!(body, LoginPage::default().to_string());
|
assert_eq!(body, LoginPage::default().to_string());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -215,7 +220,7 @@ mod test {
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let s = server_with_pool(&db).await;
|
let s = server_with_pool(&db).await;
|
||||||
let resp = s.get("/logout").await;
|
let resp = s.get("/logout").await;
|
||||||
let body = std::str::from_utf8(resp.bytes()).unwrap().to_string();
|
let body = std::str::from_utf8(resp.as_bytes()).unwrap().to_string();
|
||||||
assert_eq!(body, LogoutPage.to_string());
|
assert_eq!(body, LogoutPage.to_string());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -232,7 +237,7 @@ mod test {
|
||||||
let s = server_with_pool(&db).await;
|
let s = server_with_pool(&db).await;
|
||||||
let resp = s.post("/logout").await;
|
let resp = s.post("/logout").await;
|
||||||
resp.assert_status_ok();
|
resp.assert_status_ok();
|
||||||
let body = std::str::from_utf8(resp.bytes()).unwrap();
|
let body = std::str::from_utf8(resp.as_bytes()).unwrap();
|
||||||
let default = LogoutSuccessPage.to_string();
|
let default = LogoutSuccessPage.to_string();
|
||||||
assert_eq!(body, &default);
|
assert_eq!(body, &default);
|
||||||
})
|
})
|
||||||
|
@ -263,11 +268,11 @@ mod test {
|
||||||
let logged_in = MainPage { user: Some(user) }.to_string();
|
let logged_in = MainPage { user: Some(user) }.to_string();
|
||||||
|
|
||||||
let main_page = s.get("/").await;
|
let main_page = s.get("/").await;
|
||||||
let body = std::str::from_utf8(main_page.bytes()).unwrap();
|
let body = std::str::from_utf8(main_page.as_bytes()).unwrap();
|
||||||
assert_eq!(&logged_in, body);
|
assert_eq!(&logged_in, body);
|
||||||
|
|
||||||
let resp = s.post("/logout").await;
|
let resp = s.post("/logout").await;
|
||||||
let body = std::str::from_utf8(resp.bytes()).unwrap();
|
let body = std::str::from_utf8(resp.as_bytes()).unwrap();
|
||||||
let default = LogoutSuccessPage.to_string();
|
let default = LogoutSuccessPage.to_string();
|
||||||
assert_eq!(body, &default);
|
assert_eq!(body, &default);
|
||||||
})
|
})
|
||||||
|
|
19
src/main.rs
19
src/main.rs
|
@ -1,6 +1,5 @@
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
use rand::{thread_rng, RngCore};
|
|
||||||
use tokio::signal;
|
use tokio::signal;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
use what2watch::get_db_pool;
|
use what2watch::get_db_pool;
|
||||||
|
@ -21,24 +20,16 @@ fn main() {
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let secret = {
|
let app = rt.block_on(what2watch::app(pool.clone()));
|
||||||
let mut bytes = [0u8; 64];
|
|
||||||
let mut rng = thread_rng();
|
|
||||||
rng.fill_bytes(&mut bytes);
|
|
||||||
bytes
|
|
||||||
};
|
|
||||||
|
|
||||||
let app = rt.block_on(what2watch::app(pool.clone(), &secret));
|
|
||||||
|
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let addr: SocketAddr = ([0, 0, 0, 0], 3000).into();
|
let addr: SocketAddr = ([0, 0, 0, 0], 3000).into();
|
||||||
tracing::debug!("binding to {addr:?}");
|
tracing::debug!("binding to {addr:?}");
|
||||||
|
|
||||||
axum::Server::bind(&addr)
|
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
|
||||||
.serve(app)
|
axum::serve(listener, app).await.unwrap();
|
||||||
.with_graceful_shutdown(shutdown_signal())
|
//.with_graceful_shutdown(shutdown_signal()) // removed in 0.7 because of upstream dep changes
|
||||||
.await
|
|
||||||
.unwrap_or_default();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
rt.block_on(pool.close());
|
rt.block_on(pool.close());
|
||||||
|
|
|
@ -235,7 +235,7 @@ mod test {
|
||||||
let server = server_with_pool(&pool).await;
|
let server = server_with_pool(&pool).await;
|
||||||
|
|
||||||
let resp = server.get("/signup").await;
|
let resp = server.get("/signup").await;
|
||||||
let body = std::str::from_utf8(resp.bytes()).unwrap();
|
let body = std::str::from_utf8(resp.as_bytes()).unwrap();
|
||||||
let expected = SignupPage::default().to_string();
|
let expected = SignupPage::default().to_string();
|
||||||
assert_eq!(&expected, body);
|
assert_eq!(&expected, body);
|
||||||
});
|
});
|
||||||
|
@ -265,7 +265,7 @@ mod test {
|
||||||
let path = format!("/signup_success/{id}");
|
let path = format!("/signup_success/{id}");
|
||||||
|
|
||||||
let resp = server.get(&path).expect_success().await;
|
let resp = server.get(&path).expect_success().await;
|
||||||
let body = std::str::from_utf8(resp.bytes()).unwrap();
|
let body = std::str::from_utf8(resp.as_bytes()).unwrap();
|
||||||
let expected = SignupSuccessPage(user).to_string();
|
let expected = SignupSuccessPage(user).to_string();
|
||||||
assert_eq!(&expected, body);
|
assert_eq!(&expected, body);
|
||||||
});
|
});
|
||||||
|
@ -310,7 +310,7 @@ mod test {
|
||||||
let user = User::try_get("bad_user", &pool).await;
|
let user = User::try_get("bad_user", &pool).await;
|
||||||
assert!(user.is_err());
|
assert!(user.is_err());
|
||||||
|
|
||||||
let body = std::str::from_utf8(resp.bytes()).unwrap();
|
let body = std::str::from_utf8(resp.as_bytes()).unwrap();
|
||||||
let expected = CreateUserError(CreateUserErrorKind::PasswordMismatch).to_string();
|
let expected = CreateUserError(CreateUserErrorKind::PasswordMismatch).to_string();
|
||||||
assert_eq!(&expected, body);
|
assert_eq!(&expected, body);
|
||||||
});
|
});
|
||||||
|
@ -336,7 +336,7 @@ mod test {
|
||||||
let user = User::try_get("bad_user", &pool).await;
|
let user = User::try_get("bad_user", &pool).await;
|
||||||
assert!(user.is_err());
|
assert!(user.is_err());
|
||||||
|
|
||||||
let body = std::str::from_utf8(resp.bytes()).unwrap();
|
let body = std::str::from_utf8(resp.as_bytes()).unwrap();
|
||||||
let expected = CreateUserError(CreateUserErrorKind::BadPassword).to_string();
|
let expected = CreateUserError(CreateUserErrorKind::BadPassword).to_string();
|
||||||
assert_eq!(&expected, body);
|
assert_eq!(&expected, body);
|
||||||
});
|
});
|
||||||
|
@ -362,7 +362,7 @@ mod test {
|
||||||
let user = User::try_get("bad_user", &pool).await;
|
let user = User::try_get("bad_user", &pool).await;
|
||||||
assert!(user.is_err());
|
assert!(user.is_err());
|
||||||
|
|
||||||
let body = std::str::from_utf8(resp.bytes()).unwrap();
|
let body = std::str::from_utf8(resp.as_bytes()).unwrap();
|
||||||
let expected = CreateUserError(CreateUserErrorKind::BadPassword).to_string();
|
let expected = CreateUserError(CreateUserErrorKind::BadPassword).to_string();
|
||||||
assert_eq!(&expected, body);
|
assert_eq!(&expected, body);
|
||||||
});
|
});
|
||||||
|
@ -396,7 +396,7 @@ mod test {
|
||||||
let user = User::try_get("bad_user", &pool).await;
|
let user = User::try_get("bad_user", &pool).await;
|
||||||
assert!(user.is_err());
|
assert!(user.is_err());
|
||||||
|
|
||||||
let body = std::str::from_utf8(resp.bytes()).unwrap();
|
let body = std::str::from_utf8(resp.as_bytes()).unwrap();
|
||||||
let expected = CreateUserError(CreateUserErrorKind::BadPassword).to_string();
|
let expected = CreateUserError(CreateUserErrorKind::BadPassword).to_string();
|
||||||
assert_eq!(&expected, body);
|
assert_eq!(&expected, body);
|
||||||
});
|
});
|
||||||
|
@ -422,7 +422,7 @@ mod test {
|
||||||
let user = User::try_get("bad_user", &pool).await;
|
let user = User::try_get("bad_user", &pool).await;
|
||||||
assert!(user.is_err());
|
assert!(user.is_err());
|
||||||
|
|
||||||
let body = std::str::from_utf8(resp.bytes()).unwrap();
|
let body = std::str::from_utf8(resp.as_bytes()).unwrap();
|
||||||
let expected = CreateUserError(CreateUserErrorKind::BadUsername).to_string();
|
let expected = CreateUserError(CreateUserErrorKind::BadUsername).to_string();
|
||||||
assert_eq!(&expected, body);
|
assert_eq!(&expected, body);
|
||||||
});
|
});
|
||||||
|
@ -448,7 +448,7 @@ mod test {
|
||||||
let user = User::try_get("bad_user", &pool).await;
|
let user = User::try_get("bad_user", &pool).await;
|
||||||
assert!(user.is_err());
|
assert!(user.is_err());
|
||||||
|
|
||||||
let body = std::str::from_utf8(resp.bytes()).unwrap();
|
let body = std::str::from_utf8(resp.as_bytes()).unwrap();
|
||||||
let expected = CreateUserError(CreateUserErrorKind::BadUsername).to_string();
|
let expected = CreateUserError(CreateUserErrorKind::BadUsername).to_string();
|
||||||
assert_eq!(&expected, body);
|
assert_eq!(&expected, body);
|
||||||
});
|
});
|
||||||
|
@ -483,7 +483,7 @@ mod test {
|
||||||
|
|
||||||
assert_eq!(resp.status_code(), StatusCode::OK);
|
assert_eq!(resp.status_code(), StatusCode::OK);
|
||||||
let expected = CreateUserError(CreateUserErrorKind::AlreadyExists).to_string();
|
let expected = CreateUserError(CreateUserErrorKind::AlreadyExists).to_string();
|
||||||
let body = std::str::from_utf8(resp.bytes()).unwrap();
|
let body = std::str::from_utf8(resp.as_bytes()).unwrap();
|
||||||
assert_eq!(&expected, body);
|
assert_eq!(&expected, body);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -508,7 +508,7 @@ mod test {
|
||||||
let user = User::try_get("bad_user", &pool).await;
|
let user = User::try_get("bad_user", &pool).await;
|
||||||
assert!(user.is_err());
|
assert!(user.is_err());
|
||||||
|
|
||||||
let body = std::str::from_utf8(resp.bytes()).unwrap();
|
let body = std::str::from_utf8(resp.as_bytes()).unwrap();
|
||||||
let expected = CreateUserError(CreateUserErrorKind::BadDisplayname).to_string();
|
let expected = CreateUserError(CreateUserErrorKind::BadDisplayname).to_string();
|
||||||
assert_eq!(&expected, body);
|
assert_eq!(&expected, body);
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,8 +8,6 @@ use crate::User;
|
||||||
pub const FORM_CONTENT_TYPE: &str = "application/x-www-form-urlencoded";
|
pub const FORM_CONTENT_TYPE: &str = "application/x-www-form-urlencoded";
|
||||||
|
|
||||||
pub async fn server_with_pool(pool: &SqlitePool) -> TestServer {
|
pub async fn server_with_pool(pool: &SqlitePool) -> TestServer {
|
||||||
let secret = [0u8; 64];
|
|
||||||
|
|
||||||
let user = get_test_user();
|
let user = get_test_user();
|
||||||
|
|
||||||
insert_user_with_id(&user, pool).await;
|
insert_user_with_id(&user, pool).await;
|
||||||
|
@ -19,7 +17,7 @@ pub async fn server_with_pool(pool: &SqlitePool) -> TestServer {
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
assert!(r == 1);
|
assert!(r == 1);
|
||||||
|
|
||||||
let app = crate::app(pool.clone(), &secret).await;
|
let app = crate::app(pool.clone()).await;
|
||||||
|
|
||||||
let config = TestServerConfig {
|
let config = TestServerConfig {
|
||||||
save_cookies: true,
|
save_cookies: true,
|
||||||
|
|
|
@ -13,7 +13,7 @@ use julid::Julid;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use crate::AuthContext;
|
use crate::auth::AuthSession;
|
||||||
|
|
||||||
const USERNAME_QUERY: &str = "select * from users where username = $1";
|
const USERNAME_QUERY: &str = "select * from users where username = $1";
|
||||||
const LAST_SEEN_QUERY: &str = "update users set last_seen = (select unixepoch()) where id = $1";
|
const LAST_SEEN_QUERY: &str = "update users set last_seen = (select unixepoch()) where id = $1";
|
||||||
|
@ -94,11 +94,11 @@ impl User {
|
||||||
|
|
||||||
pub async fn handle_update_last_seen(
|
pub async fn handle_update_last_seen(
|
||||||
State(pool): State<SqlitePool>,
|
State(pool): State<SqlitePool>,
|
||||||
auth: AuthContext,
|
auth: AuthSession,
|
||||||
request: Request,
|
request: Request,
|
||||||
next: Next,
|
next: Next,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
if let Some(user) = auth.current_user {
|
if let Some(user) = auth.user {
|
||||||
if let Some(then) = user.last_seen {
|
if let Some(then) = user.last_seen {
|
||||||
let now = SystemTime::now()
|
let now = SystemTime::now()
|
||||||
.duration_since(UNIX_EPOCH)
|
.duration_since(UNIX_EPOCH)
|
||||||
|
|
|
@ -10,7 +10,7 @@ use sqlx::{query, query_as, query_scalar, SqlitePool};
|
||||||
use super::templates::{AddNewWatchPage, GetWatchPage, SearchWatchesPage};
|
use super::templates::{AddNewWatchPage, GetWatchPage, SearchWatchesPage};
|
||||||
use crate::{
|
use crate::{
|
||||||
util::{empty_string_as_none, year_to_epoch},
|
util::{empty_string_as_none, year_to_epoch},
|
||||||
AuthContext, MyWatchesPage, ShowKind, Watch, WatchQuest,
|
AuthSession, MyWatchesPage, ShowKind, Watch, WatchQuest,
|
||||||
};
|
};
|
||||||
|
|
||||||
//-************************************************************************
|
//-************************************************************************
|
||||||
|
@ -104,10 +104,8 @@ pub struct PostAddExistingWatch {
|
||||||
// handlers
|
// handlers
|
||||||
//-************************************************************************
|
//-************************************************************************
|
||||||
|
|
||||||
pub async fn get_add_new_watch(auth: AuthContext) -> impl IntoResponse {
|
pub async fn get_add_new_watch(auth: AuthSession) -> impl IntoResponse {
|
||||||
AddNewWatchPage {
|
AddNewWatchPage { user: auth.user }
|
||||||
user: auth.current_user,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct QuestQuest {
|
struct QuestQuest {
|
||||||
|
@ -118,11 +116,11 @@ struct QuestQuest {
|
||||||
|
|
||||||
/// Add a Watch to your watchlist (side effects system-add)
|
/// Add a Watch to your watchlist (side effects system-add)
|
||||||
pub async fn post_add_new_watch(
|
pub async fn post_add_new_watch(
|
||||||
auth: AuthContext,
|
auth: AuthSession,
|
||||||
State(pool): State<SqlitePool>,
|
State(pool): State<SqlitePool>,
|
||||||
Form(form): Form<PostAddNewWatch>,
|
Form(form): Form<PostAddNewWatch>,
|
||||||
) -> Result<impl IntoResponse, WatchAddError> {
|
) -> Result<impl IntoResponse, WatchAddError> {
|
||||||
if let Some(user) = auth.current_user {
|
if let Some(user) = auth.user {
|
||||||
{
|
{
|
||||||
let release_date = year_to_epoch(form.year.as_deref());
|
let release_date = year_to_epoch(form.year.as_deref());
|
||||||
let watch = Watch {
|
let watch = Watch {
|
||||||
|
@ -195,7 +193,7 @@ async fn add_new_watch_impl(
|
||||||
|
|
||||||
/// Add a Watch to your watchlist by selecting it with a checkbox
|
/// Add a Watch to your watchlist by selecting it with a checkbox
|
||||||
pub async fn post_add_watch_quest(
|
pub async fn post_add_watch_quest(
|
||||||
_auth: AuthContext,
|
_auth: AuthSession,
|
||||||
State(_pool): State<SqlitePool>,
|
State(_pool): State<SqlitePool>,
|
||||||
Form(_form): Form<PostAddExistingWatch>,
|
Form(_form): Form<PostAddExistingWatch>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
|
@ -218,7 +216,7 @@ pub async fn _add_watch_quest_impl(pool: &SqlitePool, quest: &WatchQuest) -> Res
|
||||||
|
|
||||||
/// A single Watch
|
/// A single Watch
|
||||||
pub async fn get_watch(
|
pub async fn get_watch(
|
||||||
auth: AuthContext,
|
auth: AuthSession,
|
||||||
watch: Option<Path<String>>,
|
watch: Option<Path<String>>,
|
||||||
State(pool): State<SqlitePool>,
|
State(pool): State<SqlitePool>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
|
@ -234,13 +232,13 @@ pub async fn get_watch(
|
||||||
|
|
||||||
GetWatchPage {
|
GetWatchPage {
|
||||||
watch,
|
watch,
|
||||||
user: auth.current_user,
|
user: auth.user,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// everything the user has saved
|
/// everything the user has saved
|
||||||
pub async fn get_watches(auth: AuthContext, State(pool): State<SqlitePool>) -> impl IntoResponse {
|
pub async fn get_watches(auth: AuthSession, State(pool): State<SqlitePool>) -> impl IntoResponse {
|
||||||
let user = auth.current_user;
|
let user = auth.user;
|
||||||
let watches: Vec<Watch> = if (user).is_some() {
|
let watches: Vec<Watch> = if (user).is_some() {
|
||||||
query_as(GET_SAVED_WATCHES_QUERY)
|
query_as(GET_SAVED_WATCHES_QUERY)
|
||||||
.bind(user.as_ref().unwrap().id)
|
.bind(user.as_ref().unwrap().id)
|
||||||
|
@ -255,11 +253,11 @@ pub async fn get_watches(auth: AuthContext, State(pool): State<SqlitePool>) -> i
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_search_watch(
|
pub async fn get_search_watch(
|
||||||
auth: AuthContext,
|
auth: AuthSession,
|
||||||
State(pool): State<SqlitePool>,
|
State(pool): State<SqlitePool>,
|
||||||
search: Query<SearchQuery>,
|
search: Query<SearchQuery>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let user = auth.current_user;
|
let user = auth.user;
|
||||||
|
|
||||||
let (search_string, qstring) = if search.0 != EMPTY_SEARCH_QUERY_STRUCT {
|
let (search_string, qstring) = if search.0 != EMPTY_SEARCH_QUERY_STRUCT {
|
||||||
let s = search.0;
|
let s = search.0;
|
||||||
|
|
Loading…
Reference in a new issue