From d7b0b1a5a4bb5e191aeac7fb996f62dbb9f02cad Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Sun, 17 Sep 2023 20:43:08 +0100 Subject: [PATCH] Hack together OAuth2 authorization code flow support Currently uses blocking APIs of rocksdb & oxide-auth --- .gitignore | 1 + Cargo.lock | 1980 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- Cargo.toml | 3 ++- jogre-server/Cargo.toml | 31 +++++++++++++++++++++++++++++++ jogre-server/config.toml | 5 +++++ jogre-server/src/config.rs | 20 ++++++++++++++++++++ jogre-server/src/context.rs | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jogre-server/src/main.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jogre-server/src/store.rs | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jogre-server/src/util.rs | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jogre-server/src/context/oauth2.rs | 279 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jogre-server/src/layers/auth_required.rs | 39 +++++++++++++++++++++++++++++++++++++++ jogre-server/src/layers/logger.rs | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jogre-server/src/layers/mod.rs | 2 ++ jogre-server/src/methods/mod.rs | 27 +++++++++++++++++++++++++++ jogre-server/src/methods/session.rs | 3 +++ jogre-server/src/store/rocksdb.rs | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jogre-server/templates/auth/login.html | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jogre-server/src/methods/oauth/authorize.rs | 13 +++++++++++++ jogre-server/src/methods/oauth/mod.rs | 19 +++++++++++++++++++ jogre-server/src/methods/oauth/refresh.rs | 13 +++++++++++++ jogre-server/src/methods/oauth/token.rs | 13 +++++++++++++ 22 files changed, 2939 insertions(+), 165 deletions(-) diff --git a/.gitignore b/.gitignore index 2f7896d..2c7428a 100644 --- a/.gitignore +++ a/.gitignore @@ -1,1 +1,2 @@ target/ +db/ diff --git a/Cargo.lock b/Cargo.lock index 553d60c..1ceefd8 100644 --- a/Cargo.lock +++ a/Cargo.lock @@ -1,8 +1,32 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" +dependencies = [ + "memchr", +] + +[[package]] name = "android-tzdata" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -15,6 +39,124 @@ checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", +] + +[[package]] +name = "anstream" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46" + +[[package]] +name = "anstyle-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "argon2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ba4cac0a46bc1d2912652a751c47f2a9f3a7fe89bcae2275d418f5270402f9" +dependencies = [ + "base64ct", + "blake2", + "cpufeatures", + "password-hash", +] + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "askama" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47cbc3cf73fa8d9833727bbee4835ba5c421a0d65b72daf9a7b5d0e0f9cfb57e" +dependencies = [ + "askama_derive", + "askama_escape", + "humansize", + "num-traits", + "percent-encoding", +] + +[[package]] +name = "askama_derive" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22fbe0413545c098358e56966ff22cdd039e10215ae213cfbd65032b119fc94" +dependencies = [ + "basic-toml", + "mime", + "mime_guess", + "nom", + "proc-macro2", + "quote", + "serde", + "syn", +] + +[[package]] +name = "askama_escape" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" + +[[package]] +name = "async-trait" +version = "0.1.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -22,26 +164,231 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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", + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "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]] +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", + "http-body", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-macros" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdca6a10ecad987bda04e95606ef85a5417dcaac1a78455242d72e031e2b6b62" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] [[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "basic-toml" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bfc506e7a2370ec239e1d072507b2a80c833083699d3c6fa176fbb4de8448c6" +dependencies = [ + "serde", +] + +[[package]] +name = "bincode" +version = "2.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f11ea1a0346b94ef188834a65c068a03aec181c94896d481d7a0a40d85b0ce95" +dependencies = [ + "bincode_derive", + "serde", +] + +[[package]] +name = "bincode_derive" +version = "2.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e30759b3b99a1b802a7a3aa21c85c3ded5c28e1c83170d82d70f08bbf7f3e4c" +dependencies = [ + "virtue", +] [[package]] +name = "bindgen" +version = "0.65.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + +[[package]] +name = "blake2b_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] name = "bumpalo" version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ + "jobserver", "libc", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", ] [[package]] @@ -63,6 +410,80 @@ "serde", "wasm-bindgen", "windows-targets", +] + +[[package]] +name = "clang-sys" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84ed82781cea27b43c9b106a979fe450a13a31aab0500595fb3fc06616de08e6" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + +[[package]] +name = "cookie" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7efb37c3e1ccb1ff97164ad95ac1606e8ccd35b3fa0a7d99a304c7f4a428cc24" +dependencies = [ + "percent-encoding", + "time", + "version_check", ] [[package]] @@ -70,6 +491,34 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] [[package]] name = "darling" @@ -83,305 +532,1457 @@ [[package]] name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "deranged" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" +dependencies = [ + "serde", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humansize" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" +dependencies = [ + "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", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.4.9", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "jmap-proto" +version = "0.1.0" +dependencies = [ + "chrono", + "serde", + "serde_json", + "serde_with", +] + +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + +[[package]] +name = "jogre-server" +version = "0.1.0" +dependencies = [ + "argon2", + "askama", + "axum", + "axum-macros", + "bincode", + "clap", + "futures", + "hex", + "hmac", + "oxide-auth", + "oxide-auth-axum", + "rand", + "rocksdb", + "serde", + "sha3", + "tokio", + "toml", + "tower", + "tower-cookies", + "tracing", + "tracing-subscriber", + "url", + "uuid", +] + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.148" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libm" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" + +[[package]] +name = "librocksdb-sys" +version = "0.11.0+8.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3386f101bcb4bd252d8e9d2fb41ec3b0862a15a62b478c355b2982efa469e3e" +dependencies = [ + "bindgen", + "bzip2-sys", + "cc", + "glob", + "libc", + "libz-sys", + "lz4-sys", + "zstd-sys", +] + +[[package]] +name = "libz-sys" +version = "1.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "lz4-sys" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "matchit" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed1202b2a6f884ae56f04cff409ab315c5ce26b5e58d7412e484f01fd52f52ef" + +[[package]] +name = "memchr" +version = "2.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-traits" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "oxide-auth" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e580c9b15905cc585d44bc6010113a3225c4b664d40d0a175d5a0a4022235d89" +dependencies = [ + "base64 0.13.1", + "chrono", + "hmac", + "once_cell", + "rand", + "rmp-serde", + "rust-argon2", + "serde", + "serde_derive", + "serde_json", + "sha2", + "subtle", + "url", +] + +[[package]] +name = "oxide-auth-axum" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5c4549a915268feef20fabcf85acd0172c0840c756a5d3974ca528100e52dcc" +dependencies = [ + "axum", + "oxide-auth", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "pin-project" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "prettyplease" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "rmp" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" +dependencies = [ + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + +[[package]] +name = "rocksdb" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6f170a4041d50a0ce04b0d2e14916d6ca863ea2e422689a5b694395d299ffe" +dependencies = [ + "libc", + "librocksdb-sys", +] + +[[package]] +name = "rust-argon2" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5885493fdf0be6cdff808d1533ce878d21cfa49c7086fa00c66355cd9141bfc" +dependencies = [ + "base64 0.21.4", + "blake2b_simd", + "constant_time_eq", + "crossbeam-utils", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "serde" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_path_to_error" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335" +dependencies = [ + "itoa", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ca3b16a3d82c4088f343b7480a93550b3eabe1a358569c2dfe38bbcead07237" +dependencies = [ + "base64 0.21.4", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.0.0", + "serde", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e6be15c453eb305019bfa438b1593c731f36a289a7853f7707ee29e870b3b3c" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha2" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "2.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "59bf04c28bee9043ed9ea1e41afc0552288d3aba9c6efdd78903b802926f4879" dependencies = [ - "fnv", - "ident_case", "proc-macro2", "quote", - "strsim", - "syn", + "unicode-ident", ] [[package]] -name = "darling_macro" -version = "0.20.3" +name = "sync_wrapper" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" -dependencies = [ - "darling_core", - "quote", - "syn", -] +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] -name = "deranged" -version = "0.3.8" +name = "thread_local" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ - "serde", + "cfg-if", + "once_cell", ] [[package]] -name = "equivalent" -version = "1.0.1" +name = "time" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" +dependencies = [ + "deranged", + "itoa", + "serde", + "time-core", + "time-macros", +] [[package]] -name = "fnv" -version = "1.0.7" +name = "time-core" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] -name = "hashbrown" -version = "0.12.3" +name = "time-macros" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572" +dependencies = [ + "time-core", +] [[package]] -name = "hashbrown" -version = "0.14.0" +name = "tinyvec" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] [[package]] -name = "hex" -version = "0.4.3" +name = "tinyvec_macros" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] -name = "iana-time-zone" -version = "0.1.57" +name = "tokio" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows", + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.5.4", + "tokio-macros", + "windows-sys", ] [[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" +name = "tokio-macros" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ - "cc", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "ident_case" -version = "1.0.1" +name = "toml" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +checksum = "c226a7bba6d859b63c92c4b4fe69c5b6b72d0cb897dbc8e6012298e6154cb56e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] [[package]] -name = "indexmap" -version = "1.9.3" +name = "toml_datetime" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ - "autocfg", - "hashbrown 0.12.3", "serde", ] [[package]] -name = "indexmap" -version = "2.0.0" +name = "toml_edit" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "8ff63e60a958cefbb518ae1fd6566af80d9d4be430a33f3723dfc47d1d411d95" dependencies = [ - "equivalent", - "hashbrown 0.14.0", + "indexmap 2.0.0", "serde", + "serde_spanned", + "toml_datetime", + "winnow", ] [[package]] -name = "itoa" -version = "1.0.9" +name = "tower" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "jmap-proto" -version = "0.1.0" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ - "chrono", - "serde", - "serde_json", - "serde_with", + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", ] [[package]] -name = "js-sys" -version = "0.3.64" +name = "tower-cookies" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "40f38d941a2ffd8402b36e02ae407637a9caceb693aaf2edc910437db0f36984" dependencies = [ - "wasm-bindgen", + "async-trait", + "axum-core", + "cookie", + "futures-util", + "http", + "parking_lot", + "pin-project-lite", + "tower-layer", + "tower-service", ] [[package]] -name = "libc" -version = "0.2.148" +name = "tower-layer" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" [[package]] -name = "log" -version = "0.4.20" +name = "tower-service" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] -name = "num-traits" -version = "0.2.16" +name = "tracing" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ - "autocfg", + "cfg-if", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", ] [[package]] -name = "once_cell" -version = "1.18.0" +name = "tracing-attributes" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "proc-macro2" -version = "1.0.67" +name = "tracing-core" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ - "unicode-ident", + "once_cell", + "valuable", ] [[package]] -name = "quote" -version = "1.0.33" +name = "tracing-log" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" dependencies = [ - "proc-macro2", + "lazy_static", + "log", + "tracing-core", ] [[package]] -name = "ryu" -version = "1.0.15" +name = "tracing-subscriber" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] [[package]] -name = "serde" -version = "1.0.188" +name = "try-lock" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" -dependencies = [ - "serde_derive", -] +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] -name = "serde_derive" -version = "1.0.188" +name = "typenum" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ - "proc-macro2", - "quote", - "syn", + "version_check", ] [[package]] -name = "serde_json" -version = "1.0.107" +name = "unicode-bidi" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ - "itoa", - "ryu", - "serde", + "tinyvec", ] [[package]] -name = "serde_with" -version = "3.3.0" +name = "url" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca3b16a3d82c4088f343b7480a93550b3eabe1a358569c2dfe38bbcead07237" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ - "base64", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.0.0", + "form_urlencoded", + "idna", + "percent-encoding", "serde", - "serde_json", - "serde_with_macros", - "time", ] [[package]] -name = "serde_with_macros" -version = "3.3.0" +name = "utf8parse" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e6be15c453eb305019bfa438b1593c731f36a289a7853f7707ee29e870b3b3c" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "uuid" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn", + "getrandom", + "serde", ] [[package]] -name = "strsim" -version = "0.10.0" +name = "valuable" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] -name = "syn" -version = "2.0.35" +name = "vcpkg" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59bf04c28bee9043ed9ea1e41afc0552288d3aba9c6efdd78903b802926f4879" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] -name = "time" -version = "0.3.28" +name = "version_check" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" -dependencies = [ - "deranged", - "itoa", - "serde", - "time-core", - "time-macros", -] +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] -name = "time-core" -version = "0.1.1" +name = "virtue" +version = "0.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "9dcc60c0624df774c82a0ef104151231d37da4962957d691c011c852b2473314" [[package]] -name = "time-macros" -version = "0.2.14" +name = "want" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "time-core", + "try-lock", ] [[package]] -name = "unicode-ident" -version = "1.0.12" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" @@ -436,12 +2037,43 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] [[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] name = "windows" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets", ] @@ -502,3 +2134,23 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "winnow" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" +dependencies = [ + "memchr", +] + +[[package]] +name = "zstd-sys" +version = "2.0.8+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +dependencies = [ + "cc", + "libc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index f7f1b3f..2165f73 100644 --- a/Cargo.toml +++ a/Cargo.toml @@ -1,5 +1,6 @@ [workspace] resolver = "2" members = [ - "jmap-proto" + "jmap-proto", + "jogre-server" ] diff --git a/jogre-server/Cargo.toml b/jogre-server/Cargo.toml new file mode 100644 index 0000000..a2bd799 100644 --- /dev/null +++ a/jogre-server/Cargo.toml @@ -1,0 +1,31 @@ +[package] +name = "jogre-server" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +argon2 = "0.5" +askama = "0.12" +axum = "0.6" +axum-macros = "0.3" +bincode = { version = "2.0.0-rc.3", features = ["serde"] } +clap = { version = "4.4", features = ["derive"] } +futures = "0.3.28" +hex = "0.4" +hmac = "0.12" +oxide-auth = "0.5" +oxide-auth-axum = "0.3" +rand = "0.8" +rocksdb = "0.21" +tokio = { version = "1.32", features = ["full"] } +tower = "0.4" +tower-cookies = "0.9" +toml = "0.8" +tracing = "0.1" +tracing-subscriber = "0.3" +url = "2.4" +uuid = { version = "1.4", features = ["v4", "serde"] } +serde = { version = "1.0.188", features = ["derive"] } +sha3 = "0.10" diff --git a/jogre-server/config.toml b/jogre-server/config.toml new file mode 100644 index 0000000..127ee6a 100644 --- /dev/null +++ a/jogre-server/config.toml @@ -1,0 +1,5 @@ +private-key = "mycoolatleast32byteprivatekey" + +[store] +type = "rocksdb" +path = "db" diff --git a/jogre-server/src/config.rs b/jogre-server/src/config.rs new file mode 100644 index 0000000..0e29908 100644 --- /dev/null +++ a/jogre-server/src/config.rs @@ -1,0 +1,20 @@ +use serde::Deserialize; + +use crate::store::StoreConfig; + +#[derive(Deserialize)] +#[serde(rename_all = "kebab-case")] +pub struct Config { + /// A private key used for encrypting data at rest, building CSRF tokens, + /// etc after being fed through Argon2 for key derivation. This key should + /// be at least 32 bytes long. + pub private_key: String, + /// Storage configuration, supported databases are currently `rocksdb`. + /// + /// ```toml + /// [store] + /// type = "rocksdb" + /// path = "db" + /// ``` + pub store: StoreConfig, +} diff --git a/jogre-server/src/context.rs b/jogre-server/src/context.rs new file mode 100644 index 0000000..70ffcb2 100644 --- /dev/null +++ a/jogre-server/src/context.rs @@ -1,0 +1,57 @@ +use std::sync::Arc; + +use crate::{config::Config, store::Store}; + +pub mod oauth2; + +pub struct Context { + pub oauth2: oauth2::OAuth2, + pub store: Arc, +} + +impl Context { + pub fn new(config: Config) -> Self { + let derived_keys = Arc::new(DerivedKeys::new(&config.private_key)); + let store = Arc::new(Store::from_config(config.store)); + + Self { + oauth2: oauth2::OAuth2::new(store.clone(), derived_keys), + store, + } + } +} + +pub struct DerivedKeys { + pub(crate) csrf_hmac_key: [u8; argon2::Params::DEFAULT_OUTPUT_LEN], +} + +impl DerivedKeys { + /// Salt used for deriving the CSRF HMAC key + const CSRF: &'static [u8] = b"CSRFTOKEN"; + + /// Instantiates a new [`DerivedKeys`], dropping the private key. + fn new(private_key: &str) -> Self { + let argon2 = argon2::Argon2::new( + argon2::Algorithm::Argon2id, + argon2::Version::V0x13, + argon2::Params::DEFAULT, + ); + + Self { + csrf_hmac_key: Self::derive_key(&argon2, private_key, Self::CSRF), + } + } + + fn derive_key( + argon2: &argon2::Argon2, + private_key: &str, + salt: &[u8], + ) -> [u8; argon2::Params::DEFAULT_OUTPUT_LEN] { + let mut out = [0_u8; argon2::Params::DEFAULT_OUTPUT_LEN]; + argon2 + .hash_password_into(private_key.as_bytes(), salt, &mut out) + .unwrap(); + + out + } +} diff --git a/jogre-server/src/main.rs b/jogre-server/src/main.rs new file mode 100644 index 0000000..70dbb0c 100644 --- /dev/null +++ a/jogre-server/src/main.rs @@ -1,0 +1,59 @@ +mod config; +mod context; +mod layers; +mod methods; +mod store; +mod util; + +use std::{path::PathBuf, sync::Arc}; + +use clap::Parser; +use rand::RngCore; +use tracing::info; + +use crate::{context::Context, store::UserProvider}; + +#[derive(Parser, Debug)] +#[clap(author, version, about)] +pub struct Args { + /// Path to the config file (eg. config.toml) + #[clap(long, short)] + config: PathBuf, +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + let args = Args::parse(); + + let subscriber = tracing_subscriber::fmt(); + #[cfg(debug_assertions)] + let subscriber = subscriber.pretty(); + subscriber.init(); + + let config = toml::from_str(&tokio::fs::read_to_string(&args.config).await?)?; + + let context = Arc::new(Context::new(config)); + + create_root_if_none_exists(&context).await; + + axum::Server::bind(&"0.0.0.0:8888".parse().unwrap()) + .serve(methods::router(context).into_make_service()) + .await?; + + Ok(()) +} + +async fn create_root_if_none_exists(context: &Context) { + if context.store.has_any_users().await.unwrap() { + return; + } + + let mut password = [0_u8; 32]; + rand::thread_rng().fill_bytes(&mut password); + let password = hex::encode(password); + + info!("User root created with password {password}"); + + let root = store::User::new("root".into(), &password); + context.store.create_user(root).await.unwrap(); +} diff --git a/jogre-server/src/store.rs b/jogre-server/src/store.rs new file mode 100644 index 0000000..38f1af6 100644 --- /dev/null +++ a/jogre-server/src/store.rs @@ -1,0 +1,89 @@ +mod rocksdb; + +use argon2::{password_hash::SaltString, Argon2, PasswordHash, PasswordHasher, PasswordVerifier}; +use axum::async_trait; +use rand::rngs::OsRng; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +#[derive(Serialize, Deserialize)] +pub struct User { + id: Uuid, + pub username: String, + password: String, +} + +impl User { + pub fn new(username: String, password: &str) -> Self { + let password = Argon2::default() + .hash_password(password.as_bytes(), &SaltString::generate(&mut OsRng)) + .unwrap() + .to_string(); + + Self { + id: Uuid::new_v4(), + username, + password, + } + } + + pub fn verify_password(&self, password: &str) -> bool { + let parsed_hash = PasswordHash::new(&self.password).unwrap(); + Argon2::default() + .verify_password(password.as_bytes(), &parsed_hash) + .is_ok() + } +} + +#[async_trait] +pub trait UserProvider { + type Error; + + async fn has_any_users(&self) -> Result; + + async fn create_user(&self, user: User) -> Result<(), Self::Error>; + + async fn get_by_username(&self, username: &str) -> Result, Self::Error>; +} + +#[derive(Deserialize)] +#[serde(tag = "type")] +pub enum StoreConfig { + #[serde(rename = "rocksdb")] + RocksDb(rocksdb::Config), +} + +pub enum Store { + RocksDb(rocksdb::RocksDb), +} + +impl Store { + pub fn from_config(config: StoreConfig) -> Self { + match config { + StoreConfig::RocksDb(config) => Self::RocksDb(rocksdb::RocksDb::new(config)), + } + } +} + +#[async_trait] +impl UserProvider for Store { + type Error = rocksdb::Error; + + async fn has_any_users(&self) -> Result { + match self { + Store::RocksDb(db) => db.has_any_users().await, + } + } + + async fn create_user(&self, user: User) -> Result<(), Self::Error> { + match self { + Store::RocksDb(db) => db.create_user(user).await, + } + } + + async fn get_by_username(&self, username: &str) -> Result, Self::Error> { + match self { + Store::RocksDb(db) => db.get_by_username(username).await, + } + } +} diff --git a/jogre-server/src/util.rs b/jogre-server/src/util.rs new file mode 100644 index 0000000..e9c8376 100644 --- /dev/null +++ a/jogre-server/src/util.rs @@ -1,0 +1,81 @@ +use hmac::{digest::FixedOutput, Hmac, Mac}; +use sha3::Sha3_256; +use tower_cookies::{ + cookie::{time::Duration, CookieBuilder, SameSite}, + Cookies, +}; +use tracing::warn; + +use crate::context::DerivedKeys; + +type HmacSha3 = Hmac; + +const CSRF_TOKEN_COOKIE_NAME: &str = "csrf_token"; + +#[derive(Copy, Clone)] +pub struct CsrfToken { + signed: [u8; 32], + unsigned: u128, +} + +impl CsrfToken { + pub fn new(derived_keys: &DerivedKeys) -> Self { + let unsigned = rand::random::(); + + let mut hmac = HmacSha3::new_from_slice(&derived_keys.csrf_hmac_key).unwrap(); + hmac.update(&unsigned.to_be_bytes()); + let signed = hmac.finalize_fixed().into(); + + Self { signed, unsigned } + } + + pub fn write_cookie(&self, cookies: &Cookies) { + cookies.add( + CookieBuilder::new(CSRF_TOKEN_COOKIE_NAME, hex::encode(self.signed)) + .http_only(true) + .max_age(Duration::hours(24)) + .same_site(SameSite::Strict) + // .secure(true) // TODO + .finish(), + ); + } + + #[must_use] + pub fn verify(derived_keys: &DerivedKeys, cookies: &Cookies, form_value: &str) -> bool { + let Some(cookie) = cookies.get(CSRF_TOKEN_COOKIE_NAME) else { + warn!("Missing CSRF token"); + return false; + }; + + let form_value = match hex::decode(form_value) { + Ok(v) => v, + Err(error) => { + warn!(?error, "Invalid form CSRF token"); + return false; + } + }; + + let cookie_token = match hex::decode(cookie.value()) { + Ok(v) => v, + Err(error) => { + warn!(?error, "Invalid cookie CSRF token"); + return false; + } + }; + + let mut hmac = HmacSha3::new_from_slice(&derived_keys.csrf_hmac_key).unwrap(); + hmac.update(&form_value); + + match hmac.verify_slice(&cookie_token) { + Ok(()) => true, + Err(error) => { + warn!(?error, "CSRF form value and cookie mismatch"); + false + } + } + } + + pub fn form_value(&self) -> String { + hex::encode(self.unsigned.to_be_bytes()) + } +} diff --git a/jogre-server/src/context/oauth2.rs b/jogre-server/src/context/oauth2.rs new file mode 100644 index 0000000..d409a75 100644 --- /dev/null +++ a/jogre-server/src/context/oauth2.rs @@ -1,0 +1,279 @@ +use std::{ + borrow::Cow, + str::FromStr, + sync::{Arc, Mutex}, +}; + +use askama::Template; +use axum::{ + async_trait, + body::HttpBody, + extract::FromRequest, + http::{Method, Request}, + BoxError, RequestExt, +}; +use futures::FutureExt; +use oxide_auth::{ + endpoint::{ + Authorizer, Issuer, OwnerConsent, OwnerSolicitor, QueryParameter, Registrar, Scope, + Solicitation, WebRequest, + }, + frontends::simple::{ + endpoint, + endpoint::{Generic, Vacant}, + }, + primitives::{ + grant::Grant, + prelude::{AuthMap, Client, ClientMap, RandomGenerator, TokenMap}, + registrar::RegisteredUrl, + }, +}; +use oxide_auth_axum::{OAuthRequest, OAuthResponse, WebError}; +use tower_cookies::Cookies; +use tracing::info; +use url::Url; + +use crate::{ + context::DerivedKeys, + store::{Store, UserProvider}, + util::CsrfToken, +}; + +pub struct OAuth2 { + pub registrar: ClientMap, + pub authorizer: Mutex>, + pub issuer: Mutex>, + pub derived_keys: Arc, + pub store: Arc, +} + +impl OAuth2 { + pub fn new(store: Arc, derived_keys: Arc) -> Self { + let mut registrar = ClientMap::new(); + + registrar.register_client(Client::public( + "abcdef", + RegisteredUrl::from("https://google.com/".parse::().unwrap()), + "test".parse::().unwrap(), + )); + + let authorizer = Mutex::new(AuthMap::new(RandomGenerator::new(16))); + let issuer = Mutex::new(TokenMap::new(RandomGenerator::new(16))); + + Self { + registrar, + authorizer, + issuer, + derived_keys, + store, + } + } + + pub fn resource( + &self, + request: OAuthRequest, + ) -> Result>> { + self.endpoint().resource_flow().execute(request) + } + + pub fn authorize( + &self, + request: OAuthRequestWrapper, + ) -> Result> { + self.endpoint().authorization_flow().execute(request) + } + + pub fn token( + &self, + request: OAuthRequestWrapper, + ) -> Result> { + self.endpoint().access_token_flow().execute(request) + } + + pub fn refresh( + &self, + request: OAuthRequestWrapper, + ) -> Result> { + self.endpoint().refresh_flow().execute(request) + } + + fn endpoint( + &self, + ) -> Generic< + impl Registrar + '_, + impl Authorizer + '_, + impl Issuer + '_, + Solicitor<'_>, + Vec, + > { + Generic { + registrar: &self.registrar, + authorizer: self.authorizer.lock().unwrap(), + issuer: self.issuer.lock().unwrap(), + solicitor: Solicitor { + derived_keys: &self.derived_keys, + store: &self.store, + }, + scopes: vec![Scope::from_str("test").unwrap()], + response: Vacant, + } + } +} + +pub struct Solicitor<'a> { + derived_keys: &'a DerivedKeys, + store: &'a Store, +} + +impl OwnerSolicitor for Solicitor<'_> { + fn check_consent( + &mut self, + _: &mut OAuthRequest, + _: Solicitation, + ) -> OwnerConsent { + unreachable!("OAuthRequest should only be used for resource requests") + } +} + +impl OwnerSolicitor for Solicitor<'_> { + fn check_consent( + &mut self, + req: &mut OAuthRequestWrapper, + solicitation: Solicitation, + ) -> OwnerConsent { + let auth_state = if req.method == Method::GET { + AuthState::Unauthenticated(None) + } else if let Some(((username, password), csrf_token)) = req.inner.body().and_then(|body| { + body.unique_value("username") + .zip(body.unique_value("password")) + .zip(body.unique_value("csrf_token")) + }) { + attempt_authentication( + self.derived_keys, + self.store, + &req.cookie_jar, + &username, + &password, + &csrf_token, + ) + } else { + AuthState::Unauthenticated(Some(UnauthenticatedState::MissingUserPass)) + }; + + match auth_state { + AuthState::Unauthenticated(reason) => { + info!("Soliciting auth from user due to {reason:?}"); + + let csrf_token = CsrfToken::new(self.derived_keys); + csrf_token.write_cookie(&req.cookie_jar); + + let response = OAuthResponse::default() + .content_type("text/html") + .unwrap() + .body( + &LoginForm { + reason, + csrf_token, + solicitation, + } + .render() + .unwrap(), + ); + + OwnerConsent::InProgress(response) + } + AuthState::Authenticated(username) => OwnerConsent::Authorized(username), + } + } +} + +fn attempt_authentication( + derived_keys: &DerivedKeys, + store: &Store, + cookies: &Cookies, + username: &str, + password: &str, + csrf_token: &str, +) -> AuthState { + if !CsrfToken::verify(derived_keys, cookies, csrf_token) { + return AuthState::Unauthenticated(Some(UnauthenticatedState::InvalidCsrfToken)); + } + + // TODO: actually await here + let Some(user) = store + .get_by_username(username) + .now_or_never() + .unwrap() + .unwrap() + else { + return AuthState::Unauthenticated(Some(UnauthenticatedState::InvalidUserPass)); + }; + + if user.verify_password(password) { + AuthState::Authenticated(user.username) + } else { + AuthState::Unauthenticated(Some(UnauthenticatedState::InvalidUserPass)) + } +} + +#[derive(Template)] +#[template(path = "auth/login.html")] +pub struct LoginForm<'a> { + reason: Option, + csrf_token: CsrfToken, + solicitation: Solicitation<'a>, +} + +pub enum AuthState { + Authenticated(String), + Unauthenticated(Option), +} + +#[derive(Debug)] +pub enum UnauthenticatedState { + InvalidUserPass, + MissingUserPass, + InvalidCsrfToken, +} + +pub struct OAuthRequestWrapper { + inner: OAuthRequest, + method: Method, + cookie_jar: Cookies, +} + +impl WebRequest for OAuthRequestWrapper { + type Error = WebError; + type Response = OAuthResponse; + + fn query(&mut self) -> Result, Self::Error> { + WebRequest::query(&mut self.inner) + } + + fn urlbody(&mut self) -> Result, Self::Error> { + WebRequest::urlbody(&mut self.inner) + } + + fn authheader(&mut self) -> Result>, Self::Error> { + WebRequest::authheader(&mut self.inner) + } +} + +#[async_trait] +impl FromRequest for OAuthRequestWrapper +where + B: HttpBody + Send + Sync + 'static, + B::Data: Send, + B::Error: Into, + S: Send + Sync, +{ + type Rejection = WebError; + + async fn from_request(mut req: Request, state: &S) -> Result { + Ok(Self { + method: req.method().clone(), + cookie_jar: req.extract_parts_with_state(state).await.unwrap(), + inner: OAuthRequest::from_request(req, state).await?, + }) + } +} diff --git a/jogre-server/src/layers/auth_required.rs b/jogre-server/src/layers/auth_required.rs new file mode 100644 index 0000000..75c68b0 100644 --- /dev/null +++ a/jogre-server/src/layers/auth_required.rs @@ -1,0 +1,39 @@ +use std::sync::Arc; + +use axum::{ + extract::State, + http::Request, + middleware::Next, + response::{IntoResponse, Response}, + RequestExt, +}; +use oxide_auth_axum::{OAuthResource, WebError}; +use tracing::{debug, error}; + +use crate::context::Context; + +pub async fn auth_required_middleware( + State(state): State>, + mut request: Request, + next: Next, +) -> Response { + let resource_request = match request.extract_parts::().await { + Ok(v) => v, + Err(e) => { + error!("Rejecting request due to invalid Authorization header"); + return e.into_response(); + } + }; + + let grant = match state.oauth2.resource(resource_request.into()) { + Ok(v) => v, + Err(e) => { + error!("Rejecting request due to it being unauthorized"); + return e.map_err(|e| e.pack::()).into_response(); + } + }; + + debug!(?grant, "Request authorized"); + + next.run(request).await +} diff --git a/jogre-server/src/layers/logger.rs b/jogre-server/src/layers/logger.rs new file mode 100644 index 0000000..7a262cd 100644 --- /dev/null +++ a/jogre-server/src/layers/logger.rs @@ -1,0 +1,125 @@ +//! Logs each and every request out in a format similar to that of Apache's logs. + +use std::{ + fmt::Debug, + net::SocketAddr, + task::{Context, Poll}, + time::Instant, +}; + +use axum::{ + extract, + http::{HeaderValue, Method, Request, Response}, +}; +use futures::future::{Future, FutureExt, Join, Map, Ready}; +use tower::Service; +use tracing::{error, info, instrument::Instrumented, Instrument, Span}; +use uuid::Uuid; + +pub trait GenericError: std::error::Error + Debug + Send + Sync {} + +#[derive(Clone)] +pub struct LoggingMiddleware(pub S); + +impl Service> for LoggingMiddleware +where + S: Service, Response = Response, Error = std::convert::Infallible> + + Clone + + Send + + 'static, + S::Future: Send + 'static, + S::Response: Default + Debug, + ReqBody: Send + Debug + 'static, + ResBody: Default + Send + 'static, +{ + type Response = S::Response; + type Error = S::Error; + type Future = Map< + Join, Ready>, + fn((::Output, PendingLogMessage)) -> ::Output, + >; + + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.0.poll_ready(cx) + } + + fn call(&mut self, req: Request) -> Self::Future { + let request_id = Uuid::new_v4(); + let span = tracing::info_span!("web", "request_id" = request_id.to_string().as_str()); + + let log_message = PendingLogMessage { + span: span.clone(), + ip: req + .extensions() + .get::>() + .map_or_else(|| "0.0.0.0:0".parse().unwrap(), |v| v.0), + method: req.method().clone(), + uri: req.uri().path().to_string(), + start: Instant::now(), + user_agent: req.headers().get(axum::http::header::USER_AGENT).cloned(), + }; + + futures::future::join( + self.0.call(req).instrument(span), + futures::future::ready(log_message), + ) + .map(|(response, pending_log_message)| { + let response = response.unwrap(); + pending_log_message.log(&response); + Ok(response) + }) + } +} + +pub struct PendingLogMessage { + span: Span, + ip: SocketAddr, + method: Method, + uri: String, + start: Instant, + user_agent: Option, +} + +impl PendingLogMessage { + pub fn log(&self, response: &Response) { + let _enter = self.span.enter(); + + if response.status().is_server_error() { + error!( + "{ip} - \"{method} {uri}\" {status} {duration:?} \"{user_agent}\" \"{error:?}\"", + ip = self.ip, + method = self.method, + uri = self.uri, + status = response.status().as_u16(), + duration = self.start.elapsed(), + user_agent = self + .user_agent + .as_ref() + .and_then(|v| v.to_str().ok()) + .unwrap_or("unknown"), + error = match response.extensions().get::>() { + Some(e) => Err(e), + None => Ok(()), + } + ); + } else { + info!( + "{ip} - \"{method} {uri}\" {status} {duration:?} \"{user_agent}\" \"{error:?}\"", + ip = self.ip, + method = self.method, + uri = self.uri, + status = response.status().as_u16(), + duration = self.start.elapsed(), + user_agent = self + .user_agent + .as_ref() + .and_then(|v| v.to_str().ok()) + .unwrap_or("unknown"), + error = match response.extensions().get::>() { + Some(e) => Err(e), + None => Ok(()), + } + ); + } + } +} diff --git a/jogre-server/src/layers/mod.rs b/jogre-server/src/layers/mod.rs new file mode 100644 index 0000000..979f74c 100644 --- /dev/null +++ a/jogre-server/src/layers/mod.rs @@ -1,0 +1,2 @@ +pub mod auth_required; +pub mod logger; diff --git a/jogre-server/src/methods/mod.rs b/jogre-server/src/methods/mod.rs new file mode 100644 index 0000000..3d1ee69 100644 --- /dev/null +++ a/jogre-server/src/methods/mod.rs @@ -1,0 +1,27 @@ +mod oauth; +mod session; + +use std::sync::Arc; + +use axum::{routing::get, Router}; +use tower::layer::layer_fn; +use tower_cookies::CookieManagerLayer; + +use crate::{ + context::Context, + layers::{auth_required::auth_required_middleware, logger::LoggingMiddleware}, +}; + +pub fn router(context: Arc) -> Router { + Router::new() + .route("/.well-known/jmap", get(session::get)) + // only apply auth requirement on endpoints above + .layer(axum::middleware::from_fn_with_state( + context.clone(), + auth_required_middleware, + )) + .nest("/oauth", oauth::router()) + .layer(layer_fn(LoggingMiddleware)) + .layer(CookieManagerLayer::new()) + .with_state(context) +} diff --git a/jogre-server/src/methods/session.rs b/jogre-server/src/methods/session.rs new file mode 100644 index 0000000..12c1120 100644 --- /dev/null +++ a/jogre-server/src/methods/session.rs @@ -1,0 +1,3 @@ +pub async fn get() -> &'static str { + "hello world" +} diff --git a/jogre-server/src/store/rocksdb.rs b/jogre-server/src/store/rocksdb.rs new file mode 100644 index 0000000..76fe878 100644 --- /dev/null +++ a/jogre-server/src/store/rocksdb.rs @@ -1,0 +1,103 @@ +use std::path::PathBuf; + +use axum::async_trait; +use rocksdb::{IteratorMode, Options, DB}; +use serde::Deserialize; + +use crate::store::{User, UserProvider}; + +#[derive(Debug)] +pub enum Error {} + +const USER_BY_USERNAME_CF: &str = "users_by_username"; +const USER_BY_UUID_CF: &str = "users_by_uuid"; + +const BINCODE_CONFIG: bincode::config::Configuration = bincode::config::standard(); + +#[derive(Deserialize)] +#[serde(rename_all = "kebab-case")] +pub struct Config { + path: PathBuf, +} + +// TODO: lots of blocking on async thread +pub struct RocksDb { + db: DB, +} + +impl RocksDb { + pub fn new(config: Config) -> Self { + let mut db_options = Options::default(); + db_options.create_if_missing(true); + db_options.create_missing_column_families(true); + + let db = DB::open_cf( + &db_options, + config.path, + [USER_BY_USERNAME_CF, USER_BY_UUID_CF], + ) + .unwrap(); + + Self { db } + } +} + +#[async_trait] +impl UserProvider for RocksDb { + type Error = Error; + + async fn has_any_users(&self) -> Result { + let by_uuid_handle = self.db.cf_handle(USER_BY_UUID_CF).unwrap(); + Ok(self + .db + .full_iterator_cf(by_uuid_handle, IteratorMode::Start) + .next() + .is_some()) + } + + async fn create_user(&self, user: User) -> Result<(), Self::Error> { + let bytes = bincode::serde::encode_to_vec(&user, BINCODE_CONFIG).unwrap(); + + let by_uuid_handle = self.db.cf_handle(USER_BY_UUID_CF).unwrap(); + self.db + .put_cf(by_uuid_handle, user.id.as_bytes(), bytes) + .unwrap(); + + let by_username_handle = self.db.cf_handle(USER_BY_USERNAME_CF).unwrap(); + self.db + .put_cf( + by_username_handle, + user.username.as_bytes(), + user.id.as_bytes(), + ) + .unwrap(); + + Ok(()) + } + + async fn get_by_username(&self, username: &str) -> Result, Error> { + let uuid = { + let by_username_handle = self.db.cf_handle(USER_BY_USERNAME_CF).unwrap(); + self.db.get_pinned_cf(by_username_handle, username).unwrap() + }; + + let Some(uuid) = uuid else { + return Ok(None); + }; + + let user_bytes = { + let by_uuid_handle = self.db.cf_handle(USER_BY_UUID_CF).unwrap(); + self.db.get_pinned_cf(by_uuid_handle, &uuid).unwrap() + }; + + let Some(user_bytes) = user_bytes else { + return Ok(None); + }; + + Ok(Some( + bincode::serde::decode_from_slice(&user_bytes, BINCODE_CONFIG) + .unwrap() + .0, + )) + } +} diff --git a/jogre-server/templates/auth/login.html b/jogre-server/templates/auth/login.html new file mode 100644 index 0000000..81d7bc0 100644 --- /dev/null +++ a/jogre-server/templates/auth/login.html @@ -1,0 +1,142 @@ + + + + + Login | Jogre + + + + + +
+ {% if let Some(reason) = reason %} +
+ {% match reason %} + {% when UnauthenticatedState::InvalidUserPass %} + Invalid username or password + {% when UnauthenticatedState::MissingUserPass %} + You must enter a username and password + {% when UnauthenticatedState::InvalidCsrfToken %} + Invalid CSRF token + {% endmatch %} +
+ {% endif %} + +
+
+ + Please login to confirm you would like to allow + {{ solicitation.pre_grant().client_id }} + access + {% if solicitation.pre_grant().scope.iter().next().is_some() %} + to {{ solicitation.pre_grant().scope }} + {% endif %} + via {{ solicitation.pre_grant().redirect_uri }}. + +
+ +
+ + + + + + + + + +
+
+
+ +diff --git a/jogre-server/src/methods/oauth/authorize.rs b/jogre-server/src/methods/oauth/authorize.rs new file mode 100644 index 0000000..0cf85da 100644 --- /dev/null +++ a/jogre-server/src/methods/oauth/authorize.rs @@ -1,0 +1,13 @@ +use std::sync::Arc; + +use axum::extract::State; +use oxide_auth_axum::{OAuthResponse, WebError}; + +use crate::context::{oauth2::OAuthRequestWrapper, Context}; + +pub async fn handle( + State(context): State>, + request: OAuthRequestWrapper, +) -> Result { + context.oauth2.authorize(request).map_err(|e| e.pack()) +} diff --git a/jogre-server/src/methods/oauth/mod.rs b/jogre-server/src/methods/oauth/mod.rs new file mode 100644 index 0000000..b90749e 100644 --- /dev/null +++ a/jogre-server/src/methods/oauth/mod.rs @@ -1,0 +1,19 @@ +mod authorize; +mod refresh; +mod token; + +use std::sync::Arc; + +use axum::{ + routing::{get, post}, + Router, +}; + +use crate::context::Context; + +pub fn router() -> Router> { + Router::new() + .route("/authorize", get(authorize::handle).post(authorize::handle)) + .route("/token", post(token::handle)) + .route("/refresh", post(refresh::handle)) +} diff --git a/jogre-server/src/methods/oauth/refresh.rs b/jogre-server/src/methods/oauth/refresh.rs new file mode 100644 index 0000000..0c4fe6a 100644 --- /dev/null +++ a/jogre-server/src/methods/oauth/refresh.rs @@ -1,0 +1,13 @@ +use std::sync::Arc; + +use axum::extract::State; +use oxide_auth_axum::{OAuthResponse, WebError}; + +use crate::context::{oauth2::OAuthRequestWrapper, Context}; + +pub async fn handle( + State(context): State>, + request: OAuthRequestWrapper, +) -> Result { + context.oauth2.refresh(request).map_err(|e| e.pack()) +} diff --git a/jogre-server/src/methods/oauth/token.rs b/jogre-server/src/methods/oauth/token.rs new file mode 100644 index 0000000..36720c5 100644 --- /dev/null +++ a/jogre-server/src/methods/oauth/token.rs @@ -1,0 +1,13 @@ +use std::sync::Arc; + +use axum::extract::State; +use oxide_auth_axum::{OAuthResponse, WebError}; + +use crate::context::{oauth2::OAuthRequestWrapper, Context}; + +pub async fn handle( + State(context): State>, + request: OAuthRequestWrapper, +) -> Result { + context.oauth2.token(request).map_err(|e| e.pack()) +} -- rgit 0.1.3