diff --git a/Cargo.lock b/Cargo.lock index f19d1ee..b4f9f1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,14 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "admin_cli" +version = "0.0.0" +dependencies = [ + "anyhow", + "fully_pub", +] + [[package]] name = "ahash" version = "0.8.11" @@ -41,9 +49,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" [[package]] name = "android-tzdata" @@ -62,9 +70,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -77,49 +85,43 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" - -[[package]] -name = "arc-swap" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "argh" @@ -140,7 +142,7 @@ dependencies = [ "argh_shared", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -172,7 +174,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -192,9 +194,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.7.7" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" dependencies = [ "async-trait", "axum-core", @@ -217,7 +219,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tokio", "tower", "tower-layer", @@ -240,7 +242,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tower-layer", "tower-service", "tracing", @@ -248,25 +250,26 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.9.4" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73c3220b188aea709cf1b6c5f9b01c3bd936bb08bd2b5184a12b35ac8131b1f9" +checksum = "c794b30c904f0a1c2fb7740f7df7f7972dfaa14ef6f57cb6178dc63e5dca2f04" dependencies = [ "axum", "axum-core", "bytes", "cookie", + "fastrand", "futures-util", "http", "http-body", "http-body-util", "mime", + "multer", "pin-project-lite", "serde", "tower", "tower-layer", "tower-service", - "tracing", ] [[package]] @@ -277,7 +280,7 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -289,14 +292,14 @@ dependencies = [ "axum", "minijinja", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "axum_typed_multipart" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0412547e063ce471a3f5ccf8a5129ae5ff64c63e40ee1bf1079dec3fcede4e7" +checksum = "41044b23e250b46af4b73286707fe517f73b3b1518cc34347ec4ae643e3e9a27" dependencies = [ "anyhow", "axum", @@ -306,22 +309,22 @@ dependencies = [ "futures-core", "futures-util", "tempfile", - "thiserror", + "thiserror 2.0.3", "tokio", "uuid", ] [[package]] name = "axum_typed_multipart_macros" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bbb13e6a88be66ca8a226e4cee4d60eea0245bbdd4f22a95dfb90cbcf6be4b3" +checksum = "aa0a06af331eb00c4f372a38664b3e4fc599bb308b2342ffdb3770b2cad3d432" dependencies = [ "darling", "heck 0.5.0", "proc-macro-error2", "quote", - "syn 2.0.79", + "syn 2.0.90", "ubyte", ] @@ -340,12 +343,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "base32" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" - [[package]] name = "base64" version = "0.21.7" @@ -405,15 +402,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" -version = "1.1.30" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ "shlex", ] @@ -441,19 +438,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" - -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "const-oid" @@ -461,12 +448,6 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[package]] -name = "constant_time_eq" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" - [[package]] name = "cookie" version = "0.18.1" @@ -486,9 +467,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -554,7 +535,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -565,7 +546,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -608,7 +589,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -628,9 +609,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] @@ -666,12 +647,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -693,15 +674,15 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "flume" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "futures-core", "futures-sink", @@ -730,7 +711,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fd8cb48eceb4e8b471af6a8e4e223cbe1286552791b9ab274512ba9cfd754df" dependencies = [ "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -785,7 +766,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -858,9 +839,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "hashlink" @@ -886,12 +867,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hex" version = "0.4.3" @@ -961,9 +936,42 @@ dependencies = [ [[package]] name = "http-range-header" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a" +checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c" + +[[package]] +name = "http_server" +version = "0.0.0" +dependencies = [ + "anyhow", + "argh", + "axum", + "axum-extra", + "axum-macros", + "axum-template", + "axum_typed_multipart", + "chrono", + "env_logger", + "fully_pub", + "jsonwebtoken", + "kernel", + "log", + "minijinja", + "minijinja-embed", + "serde", + "serde_json", + "serde_urlencoded", + "sqlx", + "strum", + "strum_macros", + "time", + "tokio", + "tower-http", + "url", + "utils", + "uuid", +] [[package]] name = "httparse" @@ -985,9 +993,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" dependencies = [ "bytes", "futures-channel", @@ -1004,9 +1012,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-util", @@ -1156,7 +1164,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -1193,7 +1201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.2", ] [[package]] @@ -1204,15 +1212,15 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "fb15147158e79fd8b8afd0252522769c4f48725460b37338544d8379d94fc8f9" dependencies = [ "wasm-bindgen", ] @@ -1232,6 +1240,27 @@ dependencies = [ "simple_asn1", ] +[[package]] +name = "kernel" +version = "0.0.0" +dependencies = [ + "anyhow", + "chrono", + "dotenvy", + "env_logger", + "fully_pub", + "log", + "serde", + "serde_json", + "sqlx", + "strum", + "strum_macros", + "toml", + "url", + "utils", + "uuid", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -1243,15 +1272,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.159" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libsqlite3-sys" @@ -1272,9 +1301,9 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litemap" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "lock_api" @@ -1330,50 +1359,11 @@ dependencies = [ "unicase", ] -[[package]] -name = "minauthator" -version = "0.1.0" -dependencies = [ - "anyhow", - "argh", - "argon2", - "axum", - "axum-extra", - "axum-macros", - "axum-template", - "axum_typed_multipart", - "base64 0.22.1", - "chrono", - "dotenvy", - "env_logger", - "fully_pub", - "jsonwebtoken", - "log", - "minijinja", - "minijinja-embed", - "rand", - "rand_core", - "redis", - "serde", - "serde_json", - "serde_urlencoded", - "sqlx", - "strum", - "strum_macros", - "time", - "tokio", - "toml", - "totp-rs", - "tower-http", - "url", - "uuid", -] - [[package]] name = "minijinja" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1028b628753a7e1a88fc59c9ba4b02ecc3bc0bd3c7af23df667bc28df9b3310e" +checksum = "2c37e1b517d1dcd0e51dc36c4567b9d5a29262b3ec8da6cb5d35e27a8fb529b5" dependencies = [ "serde", ] @@ -1401,11 +1391,10 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi", "libc", "wasi", "windows-sys 0.52.0", @@ -1583,9 +1572,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -1654,14 +1643,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] name = "proc-macro2" -version = "1.0.87" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -1705,21 +1694,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "redis" -version = "0.27.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6baebe319ef5e4b470f248335620098d1c2e9261e995be05f56f719ca4bdb2" -dependencies = [ - "arc-swap", - "combine", - "itoa", - "num-bigint", - "percent-encoding", - "ryu", - "url", -] - [[package]] name = "redox_syscall" version = "0.5.7" @@ -1731,9 +1705,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -1743,9 +1717,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -1775,9 +1749,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" dependencies = [ "const-oid", "digest", @@ -1801,9 +1775,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags", "errno", @@ -1832,29 +1806,29 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -1939,7 +1913,7 @@ checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" dependencies = [ "num-bigint", "num-traits", - "thiserror", + "thiserror 1.0.69", "time", ] @@ -1960,9 +1934,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -2043,7 +2017,7 @@ dependencies = [ "sha2", "smallvec", "sqlformat", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "tracing", @@ -2128,7 +2102,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror", + "thiserror 1.0.69", "tracing", "uuid", "whoami", @@ -2168,7 +2142,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror", + "thiserror 1.0.69", "tracing", "uuid", "whoami", @@ -2238,7 +2212,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -2260,9 +2234,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -2277,9 +2251,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" [[package]] name = "synstructure" @@ -2289,14 +2263,14 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -2307,22 +2281,42 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +dependencies = [ + "thiserror-impl 2.0.3", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", ] [[package]] @@ -2383,9 +2377,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -2405,7 +2399,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -2466,19 +2460,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "totp-rs" -version = "5.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b2f27dad992486c26b4e7455f38aa487e838d6d61b57e72906ee2b8c287a90" -dependencies = [ - "base32", - "constant_time_eq", - "hmac", - "sha1", - "sha2", -] - [[package]] name = "tower" version = "0.5.1" @@ -2497,9 +2478,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8437150ab6bbc8c5f0f519e3d5ed4aa883a83dd4cdd3d1b21f9482936046cb97" +checksum = "403fa3b783d4b626a8ad51d766ab03cb6d2dbfc46b1c5d4448395e6628dc9697" dependencies = [ "bitflags", "bytes", @@ -2534,9 +2515,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -2546,20 +2527,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] @@ -2578,12 +2559,9 @@ checksum = "f720def6ce1ee2fc44d40ac9ed6d3a59c361c80a75a7aa8e75bb9baed31cf2ea" [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-bidi" @@ -2593,9 +2571,9 @@ checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-normalization" @@ -2632,9 +2610,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.3" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -2665,11 +2643,22 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "utils" +version = "0.0.0" +dependencies = [ + "anyhow", + "argon2", + "base64 0.22.1", + "rand", + "rand_core", +] + [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom", "serde", @@ -2701,9 +2690,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "21d3b25c3ea1126a2ad5f4f9068483c2af1e64168f847abe863a526b8dbfe00b" dependencies = [ "cfg-if", "once_cell", @@ -2712,24 +2701,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "52857d4c32e496dc6537646b5b117081e71fd2ff06de792e3577a150627db283" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "920b0ffe069571ebbfc9ddc0b36ba305ef65577c94b06262ed793716a1afd981" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2737,22 +2726,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "bf59002391099644be3524e23b781fa43d2be0c5aa0719a18c0731b9d195cab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "e5047c5392700766601942795a436d7d2599af60dcc3cc1248c9120bfb0827b0" [[package]] name = "whoami" @@ -2944,9 +2933,9 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "yoke" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", @@ -2956,13 +2945,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", "synstructure", ] @@ -2984,27 +2973,27 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] name = "zerofrom" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", "synstructure", ] @@ -3033,5 +3022,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] diff --git a/Cargo.toml b/Cargo.toml index 41357f6..c6d0713 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,26 +3,26 @@ cargo-features = ["codegen-backend"] [profile.dev] codegen-backend = "cranelift" -[package] -name = "minauthator" -description = "Identity provider and OAuth2 server for an small-scale organization." -version = "0.1.0" -edition = "2021" +[workspace] +members = [ + "lib/kernel", + "lib/utils", + "lib/http_server", + "lib/admin_cli" +] -[dependencies] +[workspace.dependencies] # commons utils anyhow = "1.0" fully_pub = "0.1" -argon2 = "0.5" strum = "0.26.3" strum_macros = "0.26" uuid = { version = "1.8", features = ["serde", "v4"] } dotenvy = "0.15.7" -base64 = "0.22.1" -rand = "0.8.5" -rand_core = { version = "0.6.4", features = ["std"] } url = "2.5.3" -argh = "0.1" # for CLI + +# CLI +argh = "0.1" # Async tokio = { version = "1.40.0", features = ["rt-multi-thread"] } @@ -34,7 +34,6 @@ env_logger = "0.11" # Serialization serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -serde_urlencoded = "0.7.1" toml = "0.8" chrono = { version = "0.4", features = ["serde"] } @@ -43,21 +42,6 @@ chrono = { version = "0.4", features = ["serde"] } sqlx = { version = "0.7.4", features = ["sqlite", "runtime-tokio", "chrono", "uuid"] } redis = { version = "0.27.3", default-features = false, features = ["acl"] } -# Web -axum = { version = "0.7.7", features = ["json", "multipart"] } -axum-extra = { version = "0.9.4", features = ["cookie"] } -axum-template = { version = "2.4.0", features = ["minijinja"] } -axum_typed_multipart = "0.13.1" -minijinja = { version = "2.1", features = ["builtins"] } -# to make work the static assets server -tower-http = { version = "0.6.1", features = ["fs"] } - # Auth utils totp-rs = "5.6" -minijinja-embed = "2.3.1" -axum-macros = "0.4.2" -jsonwebtoken = "9.3.0" -time = "0.3.36" -[build-dependencies] -minijinja-embed = "2.3.1" diff --git a/docs/draft.md b/docs/draft.md index aa65361..5a962c7 100644 --- a/docs/draft.md +++ b/docs/draft.md @@ -3,3 +3,7 @@ https://datatracker.ietf.org/doc/html/rfc6749 https://stackoverflow.com/questions/79118231/how-to-access-the-axum-request-path-in-a-minijinja-template + +## Oauth2 test + +-> authorize diff --git a/justfile b/justfile index 4f04243..8bc1c40 100644 --- a/justfile +++ b/justfile @@ -1,11 +1,12 @@ export RUST_BACKTRACE := "1" export RUST_LOG := "trace" +export RUN_ARGS := "run --bin minauthator-server -- --config ./config.toml --database ./tmp/dbs/minauthator.db --static-assets ./assets" watch-run: - cargo-watch -x 'run -- --config ./config.toml --database ./tmp/dbs/minauthator.db --static-assets ./assets' + cargo-watch -x "$RUN_ARGS" run: - cargo run -- --database ./tmp/dbs/minauthator.db --config ./config.toml --static-assets ./assets + cargo $RUN_ARGS docker-run: docker run -p 3085:8080 -v ./tmp/docker/config:/etc/minauthator -v ./tmp/docker/db:/var/lib/minauthator minauthator diff --git a/lib/admin_cli/Cargo.toml b/lib/admin_cli/Cargo.toml new file mode 100644 index 0000000..97e0107 --- /dev/null +++ b/lib/admin_cli/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "admin_cli" +edition = "2021" + +[dependencies] +anyhow = { workspace = true } +fully_pub = { workspace = true } + +[[bin]] +name = "minauthator-admin" +path = "src/main.rs" diff --git a/lib/admin_cli/src/main.rs b/lib/admin_cli/src/main.rs new file mode 100644 index 0000000..9cf2d88 --- /dev/null +++ b/lib/admin_cli/src/main.rs @@ -0,0 +1,6 @@ +use anyhow::Result; + +fn main() -> Result<()> { + println!("Starting minauthator admin CLI"); + Ok(()) +} diff --git a/lib/http_server/Cargo.toml b/lib/http_server/Cargo.toml new file mode 100644 index 0000000..8695cf6 --- /dev/null +++ b/lib/http_server/Cargo.toml @@ -0,0 +1,51 @@ +[package] +name = "http_server" +edition = "2021" + +[dependencies] +kernel = { path = "../kernel" } +utils = { path = "../utils" } + +# common +log = { workspace = true } +env_logger = { workspace = true } + +strum = { workspace = true } +strum_macros = { workspace = true } + +anyhow = { workspace = true } +fully_pub = { workspace = true } + +tokio = { workspace = true } + +# Web +axum = { version = "0.7.7", features = ["json", "multipart"] } +axum-extra = { version = "0.9.4", features = ["cookie"] } +axum-template = { version = "2.4.0", features = ["minijinja"] } +axum_typed_multipart = "0.13.1" +minijinja = { version = "2.1", features = ["builtins"] } +# to make work the static assets server +tower-http = { version = "0.6.1", features = ["fs"] } + +minijinja-embed = "2.3.1" +axum-macros = "0.4.2" +jsonwebtoken = "9.3.0" +time = "0.3.36" + +serde = { workspace = true } +serde_json = { workspace = true } +serde_urlencoded = "0.7.1" +chrono = { workspace = true } + +argh = { workspace = true } + +sqlx = { workspace = true } +uuid = { workspace = true } +url = { workspace = true } + +[build-dependencies] +minijinja-embed = "2.3.1" + +[[bin]] +name = "minauthator-server" +path = "src/main.rs" diff --git a/build.rs b/lib/http_server/build.rs similarity index 100% rename from build.rs rename to lib/http_server/build.rs diff --git a/lib/http_server/src/controllers/api/index.rs b/lib/http_server/src/controllers/api/index.rs new file mode 100644 index 0000000..9253ece --- /dev/null +++ b/lib/http_server/src/controllers/api/index.rs @@ -0,0 +1,14 @@ +use axum::{extract::State, response::IntoResponse, Json}; +use serde_json::json; + +use crate::AppState; + +pub async fn get_index( + State(app_state): State, +) -> impl IntoResponse { + Json(json!({ + "software": "Minauthator", + "name": app_state.config.instance.name, + "base_uri": app_state.config.instance.base_uri + })) +} diff --git a/src/controllers/api/mod.rs b/lib/http_server/src/controllers/api/mod.rs similarity index 77% rename from src/controllers/api/mod.rs rename to lib/http_server/src/controllers/api/mod.rs index 36f3a8e..eef80ff 100644 --- a/src/controllers/api/mod.rs +++ b/lib/http_server/src/controllers/api/mod.rs @@ -1,3 +1,4 @@ +pub mod index; pub mod oauth2; pub mod read_user; pub mod openid; diff --git a/src/controllers/api/oauth2/access_token.rs b/lib/http_server/src/controllers/api/oauth2/access_token.rs similarity index 95% rename from src/controllers/api/oauth2/access_token.rs rename to lib/http_server/src/controllers/api/oauth2/access_token.rs index b0d9c54..1da6993 100644 --- a/src/controllers/api/oauth2/access_token.rs +++ b/lib/http_server/src/controllers/api/oauth2/access_token.rs @@ -4,10 +4,9 @@ use fully_pub::fully_pub; use log::error; use serde::{Deserialize, Serialize}; +use kernel::models::authorization::Authorization; use crate::{ - models::{authorization::Authorization, token_claims::AppUserTokenClaims}, - server::AppState, - services::{app_session::AppClientSession, session::create_token} + services::{app_session::AppClientSession, session::create_token}, token_claims::AppUserTokenClaims, AppState }; const AUTHORIZATION_CODE_TTL_SECONDS: i64 = 120; @@ -43,7 +42,7 @@ pub async fn get_access_token( ) .bind(&form.code) .bind(&app_client_session.client_id) - .fetch_one(&app_state.db) + .fetch_one(&app_state.db.0) .await; let authorization = match authorizations_res { Ok(val) => val, diff --git a/src/controllers/api/oauth2/mod.rs b/lib/http_server/src/controllers/api/oauth2/mod.rs similarity index 100% rename from src/controllers/api/oauth2/mod.rs rename to lib/http_server/src/controllers/api/oauth2/mod.rs diff --git a/src/controllers/api/openid/mod.rs b/lib/http_server/src/controllers/api/openid/mod.rs similarity index 100% rename from src/controllers/api/openid/mod.rs rename to lib/http_server/src/controllers/api/openid/mod.rs diff --git a/src/controllers/api/openid/well_known.rs b/lib/http_server/src/controllers/api/openid/well_known.rs similarity index 93% rename from src/controllers/api/openid/well_known.rs rename to lib/http_server/src/controllers/api/openid/well_known.rs index 64ac5a3..54daf3e 100644 --- a/src/controllers/api/openid/well_known.rs +++ b/lib/http_server/src/controllers/api/openid/well_known.rs @@ -1,9 +1,10 @@ use axum::{extract::State, response::IntoResponse, Json}; use fully_pub::fully_pub; +use kernel::models::authorization::AuthorizationScope; use serde::Serialize; use strum::IntoEnumIterator; -use crate::{models::authorization::AuthorizationScope, server::AppState}; +use crate::AppState; #[derive(Serialize)] #[fully_pub] diff --git a/src/controllers/api/read_user.rs b/lib/http_server/src/controllers/api/read_user.rs similarity index 83% rename from src/controllers/api/read_user.rs rename to lib/http_server/src/controllers/api/read_user.rs index a6b34dd..4b9e7c1 100644 --- a/src/controllers/api/read_user.rs +++ b/lib/http_server/src/controllers/api/read_user.rs @@ -2,7 +2,8 @@ use axum::{extract::State, response::IntoResponse, Extension, Json}; use fully_pub::fully_pub; use serde::Serialize; -use crate::{models::{token_claims::AppUserTokenClaims, user::User}, server::AppState}; +use crate::{token_claims::AppUserTokenClaims, AppState}; +use kernel::models::user::User; #[derive(Serialize)] #[fully_pub] @@ -19,10 +20,10 @@ pub async fn read_user_basic( State(app_state): State, Extension(token_claims): Extension, ) -> impl IntoResponse { - // 1. This handler require client user authentification (JWT) + // 1. This handler require app user authentification (JWT) let user_res = sqlx::query_as::<_, User>("SELECT * FROM users WHERE id = $1") .bind(&token_claims.user_id) - .fetch_one(&app_state.db) + .fetch_one(&app_state.db.0) .await .expect("To get user from claim"); let output = ReadUserBasicExtract { diff --git a/src/controllers/mod.rs b/lib/http_server/src/controllers/mod.rs similarity index 100% rename from src/controllers/mod.rs rename to lib/http_server/src/controllers/mod.rs diff --git a/src/controllers/ui/admin/apps.rs b/lib/http_server/src/controllers/ui/admin/apps.rs similarity index 100% rename from src/controllers/ui/admin/apps.rs rename to lib/http_server/src/controllers/ui/admin/apps.rs diff --git a/src/controllers/ui/admin/authorizations.rs b/lib/http_server/src/controllers/ui/admin/authorizations.rs similarity index 100% rename from src/controllers/ui/admin/authorizations.rs rename to lib/http_server/src/controllers/ui/admin/authorizations.rs diff --git a/src/controllers/ui/admin/users.rs b/lib/http_server/src/controllers/ui/admin/mod.rs similarity index 100% rename from src/controllers/ui/admin/users.rs rename to lib/http_server/src/controllers/ui/admin/mod.rs diff --git a/lib/http_server/src/controllers/ui/admin/users.rs b/lib/http_server/src/controllers/ui/admin/users.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/controllers/ui/apps.rs b/lib/http_server/src/controllers/ui/apps.rs similarity index 89% rename from src/controllers/ui/apps.rs rename to lib/http_server/src/controllers/ui/apps.rs index d048cb2..05992fb 100644 --- a/src/controllers/ui/apps.rs +++ b/lib/http_server/src/controllers/ui/apps.rs @@ -1,10 +1,10 @@ use axum::{extract::State, response::IntoResponse, Extension}; use minijinja::context; +use kernel::models::{config::AppVisibility, config::Application}; use crate::{ - models::{config::AppVisibility, config::Application}, renderer::TemplateRenderer, - server::AppState + AppState }; pub async fn list_apps( diff --git a/src/controllers/ui/authorize.rs b/lib/http_server/src/controllers/ui/authorize.rs similarity index 95% rename from src/controllers/ui/authorize.rs rename to lib/http_server/src/controllers/ui/authorize.rs index 0bcb1e5..f6016c9 100644 --- a/src/controllers/ui/authorize.rs +++ b/lib/http_server/src/controllers/ui/authorize.rs @@ -7,14 +7,15 @@ use serde::{Deserialize, Serialize}; use url::Url; use uuid::Uuid; +use kernel::{ + models::{authorization::Authorization, config::AppAuthorizeFlow} +}; +use utils::get_random_alphanumerical; use crate::{ - models::{authorization::Authorization, config::AppAuthorizeFlow, token_claims::UserTokenClaims}, - renderer::TemplateRenderer, server::AppState, - services::oauth2::{parse_scope, verify_redirect_uri}, - utils::get_random_alphanumerical + renderer::TemplateRenderer, services::oauth2::{parse_scope, verify_redirect_uri}, token_claims::UserTokenClaims, AppState }; -#[derive(Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] #[fully_pub] /// query params described in [RFC6749 section 4.1.1](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1) struct AuthorizationParams { @@ -105,7 +106,7 @@ pub async fn authorize_form( .bind(&token_claims.sub) .bind(&authorization_params.client_id) .bind(sqlx::types::Json(&scopes)) - .fetch_one(&app_state.db) + .fetch_one(&app_state.db.0) .await; match authorizations_res { @@ -119,7 +120,7 @@ pub async fn authorize_form( .bind(existing_authorization.id) .bind(authorization_code.clone()) .bind(Utc::now().to_rfc3339_opts(SecondsFormat::Millis, true)) - .execute(&app_state.db) + .execute(&app_state.db.0) .await.unwrap(); // Authorization already given, just redirect to the app @@ -219,7 +220,7 @@ pub async fn perform_authorize( .bind(authorization.code) .bind(authorization.last_used_at.map(|x| x.to_rfc3339_opts(SecondsFormat::Millis, true))) .bind(authorization.created_at.to_rfc3339_opts(SecondsFormat::Millis, true)) - .execute(&app_state.db) + .execute(&app_state.db.0) .await; if let Err(err) = res { error!("Failed to save authorization in DB. {}", err); diff --git a/src/controllers/ui/home.rs b/lib/http_server/src/controllers/ui/home.rs similarity index 100% rename from src/controllers/ui/home.rs rename to lib/http_server/src/controllers/ui/home.rs diff --git a/src/controllers/ui/login.rs b/lib/http_server/src/controllers/ui/login.rs similarity index 88% rename from src/controllers/ui/login.rs rename to lib/http_server/src/controllers/ui/login.rs index 6bdca40..59cce05 100644 --- a/src/controllers/ui/login.rs +++ b/lib/http_server/src/controllers/ui/login.rs @@ -1,15 +1,15 @@ use axum_extra::extract::{cookie::{Cookie, SameSite}, CookieJar}; use chrono::{SecondsFormat, Utc}; +use kernel::models::user::{User, UserStatus}; use log::info; use serde::Deserialize; -use axum::{extract::{Query, State}, http::{HeaderMap, HeaderValue, StatusCode}, response::{Html, IntoResponse, Redirect}, Extension, Form}; +use axum::{extract::{Query, State}, http::StatusCode, response::{IntoResponse, Redirect}, Extension, Form}; use fully_pub::fully_pub; use minijinja::context; use time::Duration; +use utils::verify_password_hash; -use crate::{ - consts::WEB_GUI_JWT_COOKIE_NAME, models::{token_claims::UserTokenClaims, user::{User, UserStatus}}, renderer::TemplateRenderer, server::AppState, services::{password::verify_password_hash, session::create_token} -}; +use crate::{renderer::TemplateRenderer, services::session::create_token, token_claims::UserTokenClaims, AppState, WEB_GUI_JWT_COOKIE_NAME}; pub async fn login_form( Extension(renderer): Extension @@ -47,7 +47,7 @@ pub async fn perform_login( let user_res = sqlx::query_as::<_, User>("SELECT * FROM users WHERE handle = $1 OR email = $2") .bind(&login.login) .bind(&login.login) - .fetch_one(&app_state.db) + .fetch_one(&app_state.db.0) .await; let password_hash = match &user_res { @@ -87,7 +87,7 @@ pub async fn perform_login( let _result = sqlx::query("UPDATE users SET last_login_at = $2 WHERE id = $1") .bind(user.id.clone()) .bind(Utc::now().to_rfc3339_opts(SecondsFormat::Millis, true)) - .execute(&app_state.db) + .execute(&app_state.db.0) .await.unwrap(); let jwt_max_age = Duration::days(15); diff --git a/src/controllers/ui/logout.rs b/lib/http_server/src/controllers/ui/logout.rs similarity index 85% rename from src/controllers/ui/logout.rs rename to lib/http_server/src/controllers/ui/logout.rs index fd55422..256b7a6 100644 --- a/src/controllers/ui/logout.rs +++ b/lib/http_server/src/controllers/ui/logout.rs @@ -1,7 +1,7 @@ use axum::response::{IntoResponse, Redirect}; use axum_extra::extract::CookieJar; -use crate::consts::WEB_GUI_JWT_COOKIE_NAME; +use crate::WEB_GUI_JWT_COOKIE_NAME; pub async fn perform_logout( cookies: CookieJar diff --git a/src/controllers/ui/me.rs b/lib/http_server/src/controllers/ui/me.rs similarity index 93% rename from src/controllers/ui/me.rs rename to lib/http_server/src/controllers/ui/me.rs index 2a6b8c0..6d3113d 100644 --- a/src/controllers/ui/me.rs +++ b/lib/http_server/src/controllers/ui/me.rs @@ -5,10 +5,11 @@ use log::error; use minijinja::context; use crate::{ - models::{token_claims::UserTokenClaims, user::User}, + token_claims::UserTokenClaims, renderer::TemplateRenderer, - server::AppState + AppState }; +use kernel::models::user::User; pub async fn me_page( State(app_state): State, @@ -17,7 +18,7 @@ pub async fn me_page( ) -> impl IntoResponse { let user_res = sqlx::query_as::<_, User>("SELECT * FROM users WHERE id = $1") .bind(&token_claims.sub) - .fetch_one(&app_state.db) + .fetch_one(&app_state.db.0) .await .expect("To get user from claim"); @@ -38,7 +39,7 @@ pub async fn me_update_details_form( let user_res = sqlx::query_as::<_, User>("SELECT * FROM users WHERE id = $1") .bind(&token_claims.sub) - .fetch_one(&app_state.db) + .fetch_one(&app_state.db.0) .await .expect("To get user from claim"); @@ -79,12 +80,12 @@ pub async fn me_perform_update_details( .bind(details_update.full_name) .bind(details_update.website) .bind(details_update.picture.contents.to_vec()) - .execute(&app_state.db) + .execute(&app_state.db.0) .await; let user_res = sqlx::query_as::<_, User>("SELECT * FROM users WHERE id = $1") .bind(&token_claims.sub) - .fetch_one(&app_state.db) + .fetch_one(&app_state.db.0) .await .expect("To get user from claim"); diff --git a/src/controllers/ui/mod.rs b/lib/http_server/src/controllers/ui/mod.rs similarity index 100% rename from src/controllers/ui/mod.rs rename to lib/http_server/src/controllers/ui/mod.rs diff --git a/src/controllers/ui/register.rs b/lib/http_server/src/controllers/ui/register.rs similarity index 93% rename from src/controllers/ui/register.rs rename to lib/http_server/src/controllers/ui/register.rs index 28ba1db..7a902fc 100644 --- a/src/controllers/ui/register.rs +++ b/lib/http_server/src/controllers/ui/register.rs @@ -7,7 +7,10 @@ use fully_pub::fully_pub; use sqlx::types::Json; use uuid::Uuid; -use crate::{models::user::{User, UserStatus}, renderer::TemplateRenderer, server::AppState, services::password::get_password_hash}; +use crate::{renderer::TemplateRenderer, AppState}; + +use kernel::models::user::{User, UserStatus}; +use utils::get_password_hash; pub async fn register_form( State(app_state): State @@ -66,7 +69,7 @@ pub async fn perform_register( .bind(user.roles) .bind(user.password_hash) .bind(user.created_at.to_rfc3339_opts(SecondsFormat::Millis, true)) - .execute(&app_state.db) + .execute(&app_state.db.0) .await; match res { Err(err) => { @@ -93,7 +96,7 @@ pub async fn perform_register( StatusCode::OK, "pages/register", context!( - success => true + success => true ) ) } diff --git a/src/controllers/ui/user_panel/authorizations.rs b/lib/http_server/src/controllers/ui/user_panel/authorizations.rs similarity index 89% rename from src/controllers/ui/user_panel/authorizations.rs rename to lib/http_server/src/controllers/ui/user_panel/authorizations.rs index 551b769..7f691be 100644 --- a/src/controllers/ui/user_panel/authorizations.rs +++ b/lib/http_server/src/controllers/ui/user_panel/authorizations.rs @@ -4,7 +4,8 @@ use log::error; use minijinja::context; use serde::Deserialize; -use crate::{models::{authorization::Authorization, token_claims::UserTokenClaims}, renderer::TemplateRenderer, server::AppState}; +use kernel::models::authorization::Authorization; +use crate::{renderer::TemplateRenderer, token_claims::UserTokenClaims, AppState}; pub async fn get_authorizations( State(app_state): State, @@ -13,7 +14,7 @@ pub async fn get_authorizations( ) -> impl IntoResponse { let user_authorizations = sqlx::query_as::<_, Authorization>("SELECT * FROM authorizations WHERE user_id = $1") .bind(&token_claims.sub) - .fetch_all(&app_state.db) + .fetch_all(&app_state.db.0) .await .expect("To get user authorization with user_id from claim"); renderer.render( @@ -37,7 +38,7 @@ pub async fn revoke_authorization( ) -> impl IntoResponse { let delete_res = sqlx::query("DELETE FROM authorizations WHERE id = $1") .bind(&form.authorization_id) - .execute(&app_state.db) + .execute(&app_state.db.0) .await; match delete_res { Ok(_) => {}, diff --git a/src/controllers/ui/user_panel/mod.rs b/lib/http_server/src/controllers/ui/user_panel/mod.rs similarity index 100% rename from src/controllers/ui/user_panel/mod.rs rename to lib/http_server/src/controllers/ui/user_panel/mod.rs diff --git a/src/server.rs b/lib/http_server/src/lib.rs similarity index 65% rename from src/server.rs rename to lib/http_server/src/lib.rs index 6833988..cc32177 100644 --- a/src/server.rs +++ b/lib/http_server/src/lib.rs @@ -1,24 +1,22 @@ -use base64::{prelude::BASE64_STANDARD, Engine}; +pub mod controllers; +pub mod router; +pub mod services; +pub mod middlewares; +pub mod renderer; +pub mod token_claims; + use fully_pub::fully_pub; use anyhow::{Result, Context}; +use kernel::{context::AppSecrets, models::config::Config, repositories::storage::Storage}; use log::info; -use minijinja::{context, Environment}; -use sqlx::{Pool, Sqlite}; -use crate::{models::config::{AppSecrets, Config}, router::build_router}; +use minijinja::Environment; -fn build_templating_env(config: &Config) -> Environment<'static> { - let mut env = Environment::new(); +use crate::{ + router::build_router, + renderer::build_templating_env +}; - minijinja_embed::load_templates!(&mut env); - - env.add_global("gl", context! { - instance => config.instance - }); - env.add_function("encode_b64str", |bin_val: Vec| { - BASE64_STANDARD.encode(bin_val) - }); - env -} +pub const WEB_GUI_JWT_COOKIE_NAME: &str = "minauthator_jwt"; #[derive(Debug)] #[fully_pub] @@ -34,7 +32,7 @@ pub struct ServerConfig { pub struct AppState { secrets: AppSecrets, config: Config, - db: Pool, + db: Storage, templating_env: Environment<'static> } @@ -42,7 +40,7 @@ pub async fn start_http_server( server_config: ServerConfig, config: Config, secrets: AppSecrets, - db_pool: Pool + db_pool: Storage ) -> Result<()> { // build state let state = AppState { diff --git a/src/cli.rs b/lib/http_server/src/main.rs similarity index 74% rename from src/cli.rs rename to lib/http_server/src/main.rs index 9317f31..6b93ae9 100644 --- a/src/cli.rs +++ b/lib/http_server/src/main.rs @@ -1,9 +1,9 @@ use argh::FromArgs; use anyhow::{Context, Result}; +use http_server::{start_http_server, ServerConfig}; +use kernel::{consts::DEFAULT_ASSETS_PATH, context::{get_kernel_context, StartKernelConfig}}; use log::info; -use crate::{get_app_context, server::{start_http_server, ServerConfig}, DEFAULT_ASSETS_PATH}; - #[derive(Debug, FromArgs)] /// Minauthator daemon struct ServerCliFlags { @@ -27,14 +27,15 @@ struct ServerCliFlags { listen_port: u32 } -/// handle CLI arguments to start process daemon -pub async fn start_server_cli() -> Result<()> { +/// handle CLI arguments to start HTTP server daemon +#[tokio::main] +pub async fn main() -> Result<()> { info!("Starting minauth"); let flags: ServerCliFlags = argh::from_env(); - let (config, secrets, db_pool) = get_app_context(crate::StartAppConfig { + let (config, secrets, db_pool) = get_kernel_context(StartKernelConfig { config_path: flags.config, database_path: flags.database - }).await.context("Getting app context")?; + }).await.context("Getting kernel context")?; start_http_server( ServerConfig { assets_path: flags.static_assets.unwrap_or(DEFAULT_ASSETS_PATH.to_string()), diff --git a/src/middlewares/app_auth.rs b/lib/http_server/src/middlewares/app_auth.rs similarity index 95% rename from src/middlewares/app_auth.rs rename to lib/http_server/src/middlewares/app_auth.rs index defe63b..3709f8b 100644 --- a/src/middlewares/app_auth.rs +++ b/lib/http_server/src/middlewares/app_auth.rs @@ -5,9 +5,12 @@ use axum::{ response::{Html, IntoResponse, Response}, Extension }; +use utils::parse_basic_auth; use crate::{ - models::token_claims::AppUserTokenClaims, server::AppState, services::{app_session::AppClientSession, session::verify_token}, utils::parse_basic_auth + services::{app_session::AppClientSession, session::verify_token}, + token_claims::AppUserTokenClaims, + AppState }; diff --git a/src/middlewares/mod.rs b/lib/http_server/src/middlewares/mod.rs similarity index 100% rename from src/middlewares/mod.rs rename to lib/http_server/src/middlewares/mod.rs diff --git a/src/middlewares/renderer.rs b/lib/http_server/src/middlewares/renderer.rs similarity index 84% rename from src/middlewares/renderer.rs rename to lib/http_server/src/middlewares/renderer.rs index 0e01238..2886afa 100644 --- a/src/middlewares/renderer.rs +++ b/lib/http_server/src/middlewares/renderer.rs @@ -1,6 +1,5 @@ use axum::{extract::{Request, State}, http::StatusCode, middleware::Next, response::Response, Extension}; - -use crate::{models::token_claims::UserTokenClaims, renderer::TemplateRenderer, server::AppState}; +use crate::{renderer::TemplateRenderer, token_claims::UserTokenClaims, AppState}; pub async fn renderer_middleware( State(app_state): State, diff --git a/src/middlewares/user_auth.rs b/lib/http_server/src/middlewares/user_auth.rs similarity index 93% rename from src/middlewares/user_auth.rs rename to lib/http_server/src/middlewares/user_auth.rs index 095eecf..7582eb7 100644 --- a/src/middlewares/user_auth.rs +++ b/lib/http_server/src/middlewares/user_auth.rs @@ -7,7 +7,9 @@ use axum::{ use axum_extra::extract::CookieJar; use crate::{ - consts::WEB_GUI_JWT_COOKIE_NAME, models::token_claims::UserTokenClaims, server::AppState, services::session::verify_token + services::session::verify_token, + token_claims::UserTokenClaims, + AppState, WEB_GUI_JWT_COOKIE_NAME }; diff --git a/src/renderer.rs b/lib/http_server/src/renderer.rs similarity index 75% rename from src/renderer.rs rename to lib/http_server/src/renderer.rs index 9b163a0..d7b0c50 100644 --- a/src/renderer.rs +++ b/lib/http_server/src/renderer.rs @@ -1,9 +1,11 @@ use axum::{http::StatusCode, response::{Html, IntoResponse}}; use fully_pub::fully_pub; +use kernel::models::config::Config; use log::error; use minijinja::{context, Environment, Value}; +use utils::encode_base64_picture; -use crate::models::token_claims::UserTokenClaims; +use crate::token_claims::UserTokenClaims; #[derive(Debug, Clone)] @@ -43,3 +45,14 @@ impl TemplateRenderer { } } +pub fn build_templating_env(config: &Config) -> Environment<'static> { + let mut env = Environment::new(); + + minijinja_embed::load_templates!(&mut env); + + env.add_global("gl", context! { + instance => config.instance + }); + env.add_function("inline_picture", encode_base64_picture); + env +} diff --git a/src/router.rs b/lib/http_server/src/router.rs similarity index 95% rename from src/router.rs rename to lib/http_server/src/router.rs index 3836d54..d3e95b6 100644 --- a/src/router.rs +++ b/lib/http_server/src/router.rs @@ -9,7 +9,7 @@ use crate::{ app_auth, renderer::renderer_middleware }, - server::{AppState, ServerConfig} + AppState, ServerConfig }; pub fn build_router(server_config: &ServerConfig, app_state: AppState) -> Router { @@ -43,7 +43,8 @@ pub fn build_router(server_config: &ServerConfig, app_state: AppState) -> Router let api_user_routes = Router::new() .route("/api/user", get(api::read_user::read_user_basic)) - .layer(middleware::from_fn_with_state(app_state.clone(), app_auth::enforce_jwt_auth_middleware)); + .layer(middleware::from_fn_with_state(app_state.clone(), app_auth::enforce_jwt_auth_middleware)) + .route("/api", get(api::index::get_index)); let well_known_routes = Router::new() .route("/.well-known/openid-configuration", get(api::openid::well_known::get_well_known_openid_configuration)); diff --git a/src/services/app_session.rs b/lib/http_server/src/services/app_session.rs similarity index 100% rename from src/services/app_session.rs rename to lib/http_server/src/services/app_session.rs diff --git a/src/services/mod.rs b/lib/http_server/src/services/mod.rs similarity index 75% rename from src/services/mod.rs rename to lib/http_server/src/services/mod.rs index 7193e1b..ed4dda0 100644 --- a/src/services/mod.rs +++ b/lib/http_server/src/services/mod.rs @@ -1,4 +1,3 @@ -pub mod password; pub mod session; pub mod oauth2; pub mod app_session; diff --git a/src/services/oauth2.rs b/lib/http_server/src/services/oauth2.rs similarity index 87% rename from src/services/oauth2.rs rename to lib/http_server/src/services/oauth2.rs index 55b640e..ed60954 100644 --- a/src/services/oauth2.rs +++ b/lib/http_server/src/services/oauth2.rs @@ -1,7 +1,7 @@ use std::str::FromStr; use anyhow::{Result, Context}; -use crate::models::{authorization::AuthorizationScope, config::Application}; +use kernel::models::{authorization::AuthorizationScope, config::Application}; pub fn verify_redirect_uri(app: &Application, input_redirect_uri: &str) -> bool { app.allowed_redirect_uris diff --git a/src/services/session.rs b/lib/http_server/src/services/session.rs similarity index 94% rename from src/services/session.rs rename to lib/http_server/src/services/session.rs index cf55087..018e094 100644 --- a/src/services/session.rs +++ b/lib/http_server/src/services/session.rs @@ -1,8 +1,7 @@ use anyhow::Result; use serde::{de::DeserializeOwned, Serialize}; use jsonwebtoken::{encode, decode, Header, Algorithm, Validation, EncodingKey, DecodingKey}; - -use crate::models::config::AppSecrets; +use kernel::context::AppSecrets; pub fn create_token(secrets: &AppSecrets, claims: T) -> String { diff --git a/src/templates/components/footer.html b/lib/http_server/src/templates/components/footer.html similarity index 100% rename from src/templates/components/footer.html rename to lib/http_server/src/templates/components/footer.html diff --git a/src/templates/components/header.html b/lib/http_server/src/templates/components/header.html similarity index 100% rename from src/templates/components/header.html rename to lib/http_server/src/templates/components/header.html diff --git a/src/templates/layouts/base.html b/lib/http_server/src/templates/layouts/base.html similarity index 100% rename from src/templates/layouts/base.html rename to lib/http_server/src/templates/layouts/base.html diff --git a/src/templates/pages/apps.html b/lib/http_server/src/templates/pages/apps.html similarity index 100% rename from src/templates/pages/apps.html rename to lib/http_server/src/templates/pages/apps.html diff --git a/src/templates/pages/authorize.html b/lib/http_server/src/templates/pages/authorize.html similarity index 100% rename from src/templates/pages/authorize.html rename to lib/http_server/src/templates/pages/authorize.html diff --git a/src/templates/pages/home.html b/lib/http_server/src/templates/pages/home.html similarity index 100% rename from src/templates/pages/home.html rename to lib/http_server/src/templates/pages/home.html diff --git a/src/templates/pages/login.html b/lib/http_server/src/templates/pages/login.html similarity index 100% rename from src/templates/pages/login.html rename to lib/http_server/src/templates/pages/login.html diff --git a/src/templates/pages/me/details-form.html b/lib/http_server/src/templates/pages/me/details-form.html similarity index 100% rename from src/templates/pages/me/details-form.html rename to lib/http_server/src/templates/pages/me/details-form.html diff --git a/src/templates/pages/me/index.html b/lib/http_server/src/templates/pages/me/index.html similarity index 100% rename from src/templates/pages/me/index.html rename to lib/http_server/src/templates/pages/me/index.html diff --git a/src/templates/pages/register.html b/lib/http_server/src/templates/pages/register.html similarity index 100% rename from src/templates/pages/register.html rename to lib/http_server/src/templates/pages/register.html diff --git a/src/templates/pages/user_panel/authorizations.html b/lib/http_server/src/templates/pages/user_panel/authorizations.html similarity index 100% rename from src/templates/pages/user_panel/authorizations.html rename to lib/http_server/src/templates/pages/user_panel/authorizations.html diff --git a/src/models/token_claims.rs b/lib/http_server/src/token_claims.rs similarity index 95% rename from src/models/token_claims.rs rename to lib/http_server/src/token_claims.rs index 66e20d2..932b4ce 100644 --- a/src/models/token_claims.rs +++ b/lib/http_server/src/token_claims.rs @@ -1,10 +1,9 @@ use fully_pub::fully_pub; use jsonwebtoken::get_current_timestamp; +use kernel::models::authorization::AuthorizationScope; use serde::{Deserialize, Serialize}; use time::Duration; -use super::authorization::AuthorizationScope; - #[derive(Debug, Serialize, Deserialize, Clone)] #[fully_pub] struct UserTokenClaims { diff --git a/lib/kernel/Cargo.toml b/lib/kernel/Cargo.toml new file mode 100644 index 0000000..a345f83 --- /dev/null +++ b/lib/kernel/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "kernel" +edition = "2021" + +[dependencies] +utils = { path = "../utils" } + +log = { workspace = true } +env_logger = { workspace = true } +anyhow = { workspace = true } +fully_pub = { workspace = true } +strum = { workspace = true } +strum_macros = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +chrono = { workspace = true } +toml = { workspace = true } +sqlx = { workspace = true } +dotenvy = { workspace = true } + +uuid = { workspace = true } +url = { workspace = true } diff --git a/lib/kernel/src/actions/mod.rs b/lib/kernel/src/actions/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/lib/kernel/src/actions/user.rs b/lib/kernel/src/actions/user.rs new file mode 100644 index 0000000..e69de29 diff --git a/lib/kernel/src/consts.rs b/lib/kernel/src/consts.rs new file mode 100644 index 0000000..bd3bef1 --- /dev/null +++ b/lib/kernel/src/consts.rs @@ -0,0 +1,4 @@ +pub const DEFAULT_DB_PATH: &str = "/var/lib/minauthator/minauthator.db"; +pub const DEFAULT_ASSETS_PATH: &str = "/usr/local/lib/minauthator/assets"; +pub const DEFAULT_CONFIG_PATH: &str = "/etc/minauthator/config.yaml"; + diff --git a/lib/kernel/src/context.rs b/lib/kernel/src/context.rs new file mode 100644 index 0000000..af5fab3 --- /dev/null +++ b/lib/kernel/src/context.rs @@ -0,0 +1,51 @@ +use std::{env, fs}; +use anyhow::{Result, Context, anyhow}; +use fully_pub::fully_pub; + +use log::info; +use sqlx::{Pool, Sqlite}; +use crate::{ + consts::{DEFAULT_CONFIG_PATH, DEFAULT_DB_PATH}, database::prepare_database, models::config::Config, repositories::storage::Storage +}; + +/// get server config +fn get_config(path: String) -> Result { + let inp_def_yaml = fs::read_to_string(path) + .expect("Should have been able to read the the config file"); + + toml::from_str(&inp_def_yaml) + .map_err(|e| anyhow!("Failed to parse config, {:?}", e)) +} + +#[fully_pub] +struct StartKernelConfig { + config_path: Option, + database_path: Option, +} + +#[derive(Debug, Clone)] +#[fully_pub] +struct AppSecrets { + jwt_secret: String +} + +pub async fn get_kernel_context(start_config: StartKernelConfig) -> Result<(Config, AppSecrets, Storage)> { + env_logger::init(); + let _ = dotenvy::dotenv(); + + let database_path = &start_config.database_path.unwrap_or(DEFAULT_DB_PATH.to_string()); + info!("Using database file at {}", database_path); + let storage = prepare_database(database_path).await.context("Could not prepare db.")?; + + let config_path = start_config.config_path.unwrap_or(DEFAULT_CONFIG_PATH.to_string()); + info!("Using config file at {}", &config_path); + let config: Config = get_config(config_path) + .expect("Cannot get config."); + + dotenvy::dotenv().context("loading .env")?; + let secrets = AppSecrets { + jwt_secret: env::var("APP_JWT_SECRET").context("Expecting APP_JWT_SECRET env var.")? + }; + + Ok((config, secrets, storage)) +} diff --git a/src/database.rs b/lib/kernel/src/database.rs similarity index 64% rename from src/database.rs rename to lib/kernel/src/database.rs index 66077de..7e0b334 100644 --- a/src/database.rs +++ b/lib/kernel/src/database.rs @@ -1,8 +1,10 @@ use anyhow::{Context, Result}; -use sqlx::{sqlite::{SqliteConnectOptions, SqlitePoolOptions}, Pool, Sqlite, ConnectOptions}; +use sqlx::{sqlite::{SqliteConnectOptions, SqlitePoolOptions}, ConnectOptions}; use std::str::FromStr; -pub async fn prepare_database(sqlite_db_path: &str) -> Result> { +use crate::repositories::storage::Storage; + +pub async fn prepare_database(sqlite_db_path: &str) -> Result { let conn_str = format!("sqlite:{}", sqlite_db_path); let pool = SqlitePoolOptions::new() @@ -14,6 +16,6 @@ pub async fn prepare_database(sqlite_db_path: &str) -> Result> { .await .context("could not connect to database_url")?; - Ok(pool) + Ok(Storage(pool)) } diff --git a/lib/kernel/src/lib.rs b/lib/kernel/src/lib.rs new file mode 100644 index 0000000..534248a --- /dev/null +++ b/lib/kernel/src/lib.rs @@ -0,0 +1,7 @@ +pub mod models; +pub mod database; +pub mod consts; +pub mod context; +pub mod actions; +pub mod repositories; + diff --git a/src/models/authorization.rs b/lib/kernel/src/models/authorization.rs similarity index 100% rename from src/models/authorization.rs rename to lib/kernel/src/models/authorization.rs diff --git a/src/models/config.rs b/lib/kernel/src/models/config.rs similarity index 99% rename from src/models/config.rs rename to lib/kernel/src/models/config.rs index a9512b0..57a275a 100644 --- a/src/models/config.rs +++ b/lib/kernel/src/models/config.rs @@ -69,7 +69,6 @@ struct Config { roles: Vec } - #[derive(Debug, Clone)] #[fully_pub] struct AppSecrets { diff --git a/src/models/mod.rs b/lib/kernel/src/models/mod.rs similarity index 70% rename from src/models/mod.rs rename to lib/kernel/src/models/mod.rs index da715f7..37a7310 100644 --- a/src/models/mod.rs +++ b/lib/kernel/src/models/mod.rs @@ -1,4 +1,3 @@ pub mod config; pub mod user; pub mod authorization; -pub mod token_claims; diff --git a/src/models/user.rs b/lib/kernel/src/models/user.rs similarity index 100% rename from src/models/user.rs rename to lib/kernel/src/models/user.rs diff --git a/lib/kernel/src/repositories/mod.rs b/lib/kernel/src/repositories/mod.rs new file mode 100644 index 0000000..d090739 --- /dev/null +++ b/lib/kernel/src/repositories/mod.rs @@ -0,0 +1,2 @@ +pub mod storage; +pub mod users; diff --git a/lib/kernel/src/repositories/storage.rs b/lib/kernel/src/repositories/storage.rs new file mode 100644 index 0000000..bbad80c --- /dev/null +++ b/lib/kernel/src/repositories/storage.rs @@ -0,0 +1,7 @@ +use fully_pub::fully_pub; +use sqlx::{Pool, Sqlite}; + +/// storage interface +#[fully_pub] +#[derive(Clone, Debug)] +struct Storage(Pool); diff --git a/lib/kernel/src/repositories/users.rs b/lib/kernel/src/repositories/users.rs new file mode 100644 index 0000000..6ef31f4 --- /dev/null +++ b/lib/kernel/src/repositories/users.rs @@ -0,0 +1,14 @@ +// user repositories + +use crate::models::user::User; + +use super::storage::Storage; +use anyhow::{Result, Context}; + +async fn get_user_by_id(storage: &Storage, user_id: &str) -> Result { + sqlx::query_as::<_, User>("SELECT * FROM users WHERE id = $1") + .bind(user_id) + .fetch_one(&storage.0) + .await + .context("To get user from claim") +} diff --git a/lib/utils/Cargo.toml b/lib/utils/Cargo.toml new file mode 100644 index 0000000..18fc24c --- /dev/null +++ b/lib/utils/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "utils" +edition = "2021" + +[dependencies] +anyhow = { workspace = true } +argon2 = "0.5" +base64 = "0.22" +rand = "0.8.5" +rand_core = { version = "0.6.4", features = ["std"] } diff --git a/src/utils.rs b/lib/utils/src/lib.rs similarity index 92% rename from src/utils.rs rename to lib/utils/src/lib.rs index 4afce48..bb524dc 100644 --- a/src/utils.rs +++ b/lib/utils/src/lib.rs @@ -61,3 +61,7 @@ pub fn parse_basic_auth(header_value: &str) -> Result<(String, String)> { )) } +pub fn encode_base64_picture(picture_bytes: Vec) -> String { + let encoded = BASE64_STANDARD.encode(picture_bytes); + return format!("data:image/*;base64,{}", encoded); +} diff --git a/src/consts.rs b/src/consts.rs deleted file mode 100644 index 1d9bd00..0000000 --- a/src/consts.rs +++ /dev/null @@ -1 +0,0 @@ -pub const WEB_GUI_JWT_COOKIE_NAME: &str = "minauthator_jwt"; diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 016a7bd..0000000 --- a/src/main.rs +++ /dev/null @@ -1,62 +0,0 @@ -pub mod models; -pub mod controllers; -pub mod router; -pub mod server; -pub mod database; -pub mod cli; -pub mod utils; -pub mod services; -pub mod middlewares; -pub mod renderer; -pub mod consts; - -use std::{env, fs}; -use anyhow::{Result, Context, anyhow}; - -use database::prepare_database; -use log::info; -use sqlx::{Pool, Sqlite}; -use models::config::{AppSecrets, Config}; - -pub const DEFAULT_DB_PATH: &str = "/var/lib/minauthator/minauthator.db"; -pub const DEFAULT_ASSETS_PATH: &str = "/usr/local/lib/minauthator/assets"; -pub const DEFAULT_CONFIG_PATH: &str = "/etc/minauthator/config.yaml"; - -fn get_config(path: String) -> Result { - let inp_def_yaml = fs::read_to_string(path) - .expect("Should have been able to read the the config file"); - - toml::from_str(&inp_def_yaml) - .map_err(|e| anyhow!("Failed to parse config, {:?}", e)) -} - -struct StartAppConfig { - config_path: Option, - database_path: Option, -} - -#[tokio::main] -async fn main() -> Result<()> { - cli::start_server_cli().await -} - -async fn get_app_context(start_app_config: StartAppConfig) -> Result<(Config, AppSecrets, Pool)> { - env_logger::init(); - let _ = dotenvy::dotenv(); - - let database_path = &start_app_config.database_path.unwrap_or(DEFAULT_DB_PATH.to_string()); - info!("Using database file at {}", database_path); - let pool = prepare_database(database_path).await.context("Could not prepare db.")?; - - let config_path = start_app_config.config_path.unwrap_or(DEFAULT_CONFIG_PATH.to_string()); - info!("Using config file at {}", &config_path); - let config: Config = get_config(config_path) - .expect("Cannot get config."); - - dotenvy::dotenv().context("loading .env")?; - let secrets = AppSecrets { - jwt_secret: env::var("APP_JWT_SECRET").context("Expecting APP_JWT_SECRET env var.")? - }; - - Ok((config, secrets, pool)) -} diff --git a/src/services/password.rs b/src/services/password.rs deleted file mode 100644 index c9e246b..0000000 --- a/src/services/password.rs +++ /dev/null @@ -1,35 +0,0 @@ -use anyhow::{anyhow, Result}; -use argon2::{ - password_hash::{ - rand_core::OsRng, - PasswordHash, PasswordHasher, PasswordVerifier, SaltString - }, - Argon2 -}; - -pub fn get_password_hash(password: String) -> Result<(String, String)> { - let salt = SaltString::generate(&mut OsRng); - - // Argon2 with default params (Argon2id v19) - let argon2 = Argon2::default(); - - // Hash password to PHC string ($argon2id$v=19$...) - match argon2.hash_password(password.as_bytes(), &salt) { - Ok(val) => Ok((salt.to_string(), val.to_string())), - Err(_) => Err(anyhow!("Failed to process password.")) - } -} - -pub fn verify_password_hash(password_hash: String, password: String) -> Result<()> { - let parsed_hash = match PasswordHash::new(&password_hash) { - Ok(val) => val, - Err(_) => { - return Err(anyhow!("Failed to parse password hash")); - } - }; - match Argon2::default().verify_password(password.as_bytes(), &parsed_hash) { - Ok(()) => Ok(()), - Err(_) => Err(anyhow!("Failed to verify password.")) - } -} - diff --git a/tests/hurl_integration/run_scenario.sh b/tests/hurl_integration/run_scenario.sh new file mode 100755 index 0000000..c723ee3 --- /dev/null +++ b/tests/hurl_integration/run_scenario.sh @@ -0,0 +1,39 @@ +#!/usr/bin/sh + +set -eou pipefail + +scenario_name="$1" +project_root="$(dirname $(cargo locate-project | jq -r .root))" +scenario_dir="$project_root/tests/hurl_integration/$1" +scenario_tmp_dir_path="$project_root/tmp/tests/$scenario_name" +database_path="$project_root/tmp/tests/$scenario_name/minauthator.db" + +echo "Starting scenario $scenario_name." +mkdir -p $scenario_tmp_dir_path +if [ -f $database_path ]; then + rm $database_path +fi +sqlite3 $database_path < $project_root/migrations/all.sql + +export DB_PATH=$database_path +if [ -f $scenario_dir/init_db.sh ]; then + $scenario_dir/init_db.sh +fi + +pkill -f $project_root/target/debug/minauthator-server & +sleep 0.1 +$project_root/target/debug/minauthator-server \ + --config "$scenario_dir/config.toml" \ + --database $database_path \ + --listen-host "127.0.0.1" \ + --listen-port "8086" \ + --static-assets "$project_root/assets" & + +server_pid=$! +sleep 0.2 +hurl \ + --variable base_url="http://localhost:8086" \ + --test --error-format long \ + $scenario_dir/main.hurl +kill $server_pid +echo "End of scenario." diff --git a/tests/hurl_integration/scenario_1/config.toml b/tests/hurl_integration/scenario_1/config.toml new file mode 100644 index 0000000..ad3f58e --- /dev/null +++ b/tests/hurl_integration/scenario_1/config.toml @@ -0,0 +1,56 @@ +[instance] +base_uri = "http://localhost:8086" +name = "Example org" +logo_uri = "https://example.org/logo.png" + +[[applications]] +slug = "demo_app" +name = "Demo app" +description = "A super application where you can do everything you want." +client_id = "00000001-0000-0000-0000-000000000001" +client_secret = "dummy_client_secret" +login_uri = "https://localhost:9876" +allowed_redirect_uris = [ + "http://localhost:9090/callback", + "http://localhost:9876/callback" +] +visibility = "Internal" +authorize_flow = "Implicit" + +[[applications]] +slug = "wiki" +name = "Wiki app" +description = "The knowledge base of the exemple org." +client_id = "f9de1885-448d-44bb-8c48-7e985486a8c6" +client_secret = "49c6c16a-0a8a-4981-a60d-5cb96582cc1a" +login_uri = "https://wiki.example.org/login" +allowed_redirect_uris = [ + "https://wiki.example.org/oauth2/callback" +] +visibility = "Public" +authorize_flow = "Implicit" + +[[applications]] +slug = "private_app" +name = "Demo app" +description = "Private app you should never discover" +client_id = "c8a08783-2342-4ce3-a3cb-9dc89b6bdf" +client_secret = "this_is_the_secret" +login_uri = "https://private-app.org" +allowed_redirect_uris = [ + "http://localhost:9091/authorize", +] +visibility = "Private" +authorize_flow = "Implicit" + +[[roles]] +slug = "basic" +name = "Basic" +description = "Basic user" +default = true + +[[roles]] +slug = "admin" +name = "Administrator" +description = "Full power on organization instance" + diff --git a/tests/hurl_integration/scenario_1/init_db.sh b/tests/hurl_integration/scenario_1/init_db.sh new file mode 100755 index 0000000..11dc8ce --- /dev/null +++ b/tests/hurl_integration/scenario_1/init_db.sh @@ -0,0 +1,9 @@ +password_hash="$(echo -n "root" | argon2 salt_06cGGWYDJCZ -e)" +echo $password_hash +SQL=$(cat <