diff --git a/Cargo.lock b/Cargo.lock index 6f64c45..9a7496b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,15 +17,6 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - [[package]] name = "anstream" version = "0.6.21" @@ -236,12 +227,6 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.10.0" @@ -269,16 +254,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "bstr" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "bumpalo" version = "3.19.1" @@ -319,39 +294,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "chrono" -version = "0.4.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" -dependencies = [ - "iana-time-zone", - "num-traits", - "windows-link", -] - -[[package]] -name = "chrono-tz" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb" -dependencies = [ - "chrono", - "chrono-tz-build", - "phf", -] - -[[package]] -name = "chrono-tz-build" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1" -dependencies = [ - "parse-zoneinfo", - "phf", - "phf_codegen", -] - [[package]] name = "clap" version = "4.5.54" @@ -424,12 +366,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - [[package]] name = "cpufeatures" version = "0.2.17" @@ -454,25 +390,6 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-queue" version = "0.3.12" @@ -531,12 +448,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "deunicode" -version = "1.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abd57806937c9cc163efc8ea3910e00a62e2aeb0b8119f1793a978088f8f6b04" - [[package]] name = "digest" version = "0.10.7" @@ -630,15 +541,6 @@ dependencies = [ "regex-syntax", ] -[[package]] -name = "file-id" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc6a637b6dc58414714eddd9170ff187ecb0933d4c7024d1abbd23a3cc26e9" -dependencies = [ - "windows-sys 0.60.2", -] - [[package]] name = "find-msvc-tools" version = "0.1.7" @@ -677,15 +579,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fsevent-sys" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" -dependencies = [ - "libc", -] - [[package]] name = "futures" version = "0.3.31" @@ -809,30 +702,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "globset" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" -dependencies = [ - "aho-corasick", - "bstr", - "log", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "globwalk" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" -dependencies = [ - "bitflags 2.10.0", - "ignore", - "walkdir", -] - [[package]] name = "hashbrown" version = "0.15.5" @@ -943,15 +812,6 @@ 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 = "1.8.1" @@ -989,30 +849,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "iana-time-zone" -version = "0.1.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[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 = "icu_collections" version = "2.1.1" @@ -1115,22 +951,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "ignore" -version = "0.4.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a" -dependencies = [ - "crossbeam-deque", - "globset", - "log", - "memchr", - "regex-automata", - "same-file", - "walkdir", - "winapi-util", -] - [[package]] name = "indexmap" version = "2.12.1" @@ -1141,26 +961,6 @@ dependencies = [ "hashbrown 0.16.1", ] -[[package]] -name = "inotify" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" -dependencies = [ - "bitflags 2.10.0", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -1192,26 +992,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kqueue" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" -dependencies = [ - "bitflags 1.3.2", - "libc", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -1239,7 +1019,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ - "bitflags 2.10.0", + "bitflags", "libc", "redox_syscall 0.7.0", ] @@ -1333,7 +1113,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", - "log", "wasi", "windows-sys 0.61.2", ] @@ -1383,57 +1162,17 @@ dependencies = [ "axum", "axum-login", "displaydoc", - "notify-debouncer-full", "password-auth", "serde", "sqlx", - "tera", "thiserror 2.0.17", "tokio", - "tower-livereload", "tower-sessions", "tower-sessions-sqlx-store", "tracing", "tracing-subscriber", ] -[[package]] -name = "notify" -version = "8.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" -dependencies = [ - "bitflags 2.10.0", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "log", - "mio", - "notify-types", - "walkdir", - "windows-sys 0.60.2", -] - -[[package]] -name = "notify-debouncer-full" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375bd3a138be7bfeff3480e4a623df4cbfb55b79df617c055cd810ba466fa078" -dependencies = [ - "file-id", - "log", - "notify", - "notify-types", - "walkdir", -] - -[[package]] -name = "notify-types" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" - [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -1536,15 +1275,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "parse-zoneinfo" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24" -dependencies = [ - "regex", -] - [[package]] name = "password-auth" version = "1.0.0" @@ -1583,49 +1313,6 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" -[[package]] -name = "pest" -version = "2.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9eb05c21a464ea704b53158d358a31e6425db2f63a1a7312268b05fe2b75f7" -dependencies = [ - "memchr", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f9dbced329c441fa79d80472764b1a2c7e57123553b8519b36663a2fb234ed" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bb96d5051a78f44f43c8f712d8e810adb0ebf923fc9ed2655a7f66f63ba8ee5" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pest_meta" -version = "2.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "602113b5b5e8621770cfd490cfd90b9f84ab29bd2b0e49ad83eb6d186cef2365" -dependencies = [ - "pest", - "sha2", -] - [[package]] name = "petgraph" version = "0.8.3" @@ -1638,44 +1325,6 @@ dependencies = [ "serde", ] -[[package]] -name = "phf" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" -dependencies = [ - "phf_shared", -] - -[[package]] -name = "phf_codegen" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" -dependencies = [ - "phf_generator", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" -dependencies = [ - "phf_shared", - "rand", -] - -[[package]] -name = "phf_shared" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" -dependencies = [ - "siphasher", -] - [[package]] name = "pin-project-lite" version = "0.2.16" @@ -1793,7 +1442,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.10.0", + "bitflags", ] [[package]] @@ -1802,19 +1451,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" dependencies = [ - "bitflags 2.10.0", -] - -[[package]] -name = "regex" -version = "1.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", + "bitflags", ] [[package]] @@ -2034,28 +1671,12 @@ dependencies = [ "rand_core", ] -[[package]] -name = "siphasher" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" - [[package]] name = "slab" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" -[[package]] -name = "slug" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882a80f72ee45de3cc9a5afeb2da0331d58df69e4e7d8eeb5d3c7784ae67e724" -dependencies = [ - "deunicode", - "wasm-bindgen", -] - [[package]] name = "smallvec" version = "1.15.1" @@ -2188,7 +1809,7 @@ checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" dependencies = [ "atoi", "base64", - "bitflags 2.10.0", + "bitflags", "byteorder", "bytes", "crc", @@ -2231,7 +1852,7 @@ checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" dependencies = [ "atoi", "base64", - "bitflags 2.10.0", + "bitflags", "byteorder", "crc", "dotenvy", @@ -2343,28 +1964,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tera" -version = "1.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8004bca281f2d32df3bacd59bc67b312cb4c70cea46cbd79dbe8ac5ed206722" -dependencies = [ - "chrono", - "chrono-tz", - "globwalk", - "humansize", - "lazy_static", - "percent-encoding", - "pest", - "pest_derive", - "rand", - "regex", - "serde", - "serde_json", - "slug", - "unicode-segmentation", -] - [[package]] name = "thiserror" version = "1.0.69" @@ -2472,9 +2071,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.49.0" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ "bytes", "libc", @@ -2547,20 +2146,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" -[[package]] -name = "tower-livereload" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62a893f6b4fbc35dc32eacd6b5cf61dd49abac153ac7b3892c5725b350912e25" -dependencies = [ - "bytes", - "http", - "http-body", - "pin-project-lite", - "tokio", - "tower", -] - [[package]] name = "tower-service" version = "0.3.3" @@ -2700,12 +2285,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" -[[package]] -name = "ucd-trie" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" - [[package]] name = "unicode-bidi" version = "0.3.18" @@ -2733,12 +2312,6 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - [[package]] name = "url" version = "2.5.8" @@ -2873,65 +2446,12 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link", -] - [[package]] name = "windows-sys" version = "0.48.0" diff --git a/nixie-server/Cargo.toml b/nixie-server/Cargo.toml index 9be0ebb..5ad50b8 100644 --- a/nixie-server/Cargo.toml +++ b/nixie-server/Cargo.toml @@ -20,6 +20,3 @@ displaydoc.workspace = true password-auth = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } -tera = "1.20.1" -notify-debouncer-full = "0.6.0" -tower-livereload = "0.10.2" diff --git a/nixie-server/src/main.rs b/nixie-server/src/main.rs index e2a7493..11a227d 100644 --- a/nixie-server/src/main.rs +++ b/nixie-server/src/main.rs @@ -1,63 +1,54 @@ -use std::sync::LazyLock; -use std::time::Duration; - +use axum::Form; use axum::Router; +use axum::extract::State; use axum::http::StatusCode; use axum::response::Html; use axum::response::IntoResponse; +use axum::response::Redirect; use axum::routing::get; +use axum::routing::post; use axum_login::AuthManagerLayerBuilder; +use axum_login::AuthUser; use axum_login::AuthnBackend; use axum_login::login_required; use displaydoc::Display; -use notify_debouncer_full::DebouncedEvent; -use notify_debouncer_full::notify::EventKind; +use password_auth::generate_hash; use password_auth::verify_password; use serde::Deserialize; +use serde::Serialize; use sqlx::SqlitePool; -use tera::Context; -use tera::Tera; +use sqlx::prelude::FromRow; use thiserror::Error; use tokio::task; use tokio::task::AbortHandle; -use tower_livereload::LiveReloadLayer; use tower_sessions::ExpiredDeletion; use tower_sessions::SessionManagerLayer; use tower_sessions_sqlx_store::SqliteStore; -use tracing::error; use tracing_subscriber::EnvFilter; -pub mod users; - -pub type WebResult = Result; - -#[derive(Debug, Error, Display)] -pub enum AppError { - /// An error occurred while templating - Tera(#[from] tera::Error), -} - -impl IntoResponse for AppError { - fn into_response(self) -> axum::response::Response { - let mut error_context = Context::new(); - error_context.insert("error", &self.to_string()); - ( - StatusCode::INTERNAL_SERVER_ERROR, - Html( - render_template("internal_error.tera.html", &error_context) - .unwrap_or_else(|_| "ERROR RENDERING ERROR! FATAL".to_string()), - ), - ) - .into_response() - } -} - #[tokio::main] async fn main() -> anyhow::Result<()> { run().await } -type AuthSession = axum_login::AuthSession; +#[derive(Debug, Clone, Serialize, Deserialize, FromRow)] +struct User { + id: i64, + username: String, + password: String, +} + +impl AuthUser for User { + type Id = i64; + + fn id(&self) -> Self::Id { + self.id + } + + fn session_auth_hash(&self) -> &[u8] { + self.password.as_bytes() + } +} #[derive(Clone)] struct Backend { @@ -65,7 +56,7 @@ struct Backend { } #[derive(Debug, Clone, Deserialize)] -struct UserCredentials { +struct Credentials { username: String, password: String, } @@ -80,8 +71,8 @@ pub enum AuthBackendError { } impl AuthnBackend for Backend { - type User = users::User; - type Credentials = UserCredentials; + type User = User; + type Credentials = Credentials; type Error = AuthBackendError; async fn authenticate( @@ -94,7 +85,7 @@ impl AuthnBackend for Backend { .await?; task::spawn_blocking(move || { - Ok(user.filter(|user| verify_password(&creds.password, user.password()).is_ok())) + Ok(user.filter(|user| verify_password(&creds.password, &user.password).is_ok())) }) .await? } @@ -113,13 +104,10 @@ impl AuthnBackend for Backend { } #[derive(Debug, Clone)] -pub struct AppState { +pub(crate) struct AppState { pub db: SqlitePool, } -pub static TERA: LazyLock> = - LazyLock::new(|| Tera::new("templates/**.tera.html").unwrap().into()); - async fn run() -> anyhow::Result<()> { tracing_subscriber::fmt() .with_env_filter(EnvFilter::from_default_env()) @@ -143,54 +131,21 @@ async fn run() -> anyhow::Result<()> { let backend = Backend { db: db.clone() }; let auth_layer = AuthManagerLayerBuilder::new(backend, session_layer).build(); - let livereload = LiveReloadLayer::new(); - let reloader = livereload.reloader(); - let app = Router::new() .route("/protected", get(show_protected)) .route_layer(login_required!(Backend, login_url = "/login")) - .merge(users::routes()) + .route("/login", get(show_login)) + .route("/login", post(do_login)) + .route("/register", get(show_register)) + .route("/register", post(do_register)) .layer(auth_layer) - .layer(livereload) .with_state(AppState { db }); - let mut debouncer = notify_debouncer_full::new_debouncer( - Duration::from_millis(50), - None, - move |event: Result, Vec>| { - match event { - Ok(events) => { - if events - .iter() - .any(|ev| !matches!(ev.event.kind, EventKind::Access(_))) - { - match TERA.write().unwrap().full_reload() { - Ok(()) => { - reloader.reload(); - } - Err(error) => { - error!("Could not reload tera templates: {error}"); - } - } - } - } - Err(_e) => {} - } - }, - )?; - - debouncer.watch( - "templates/", - notify_debouncer_full::notify::RecursiveMode::Recursive, - )?; - let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); axum::serve(listener, app.into_make_service()) .with_graceful_shutdown(shutdown_signal(deletion_task.abort_handle())) .await?; - debouncer.stop(); - Ok(()) } @@ -216,10 +171,85 @@ async fn shutdown_signal(handle: AbortHandle) { handle.abort(); } -pub fn render_template(name: &str, context: &Context) -> tera::Result { - TERA.read().unwrap().render(name, context) +async fn show_protected() -> Html { + format!( + r##" + + + + Yay, you did it! + + + "## + ) + .into() } -async fn show_protected() -> Html { - Html(render_template("protected.tera.html", &Context::default()).unwrap()) +async fn show_login() -> Html { + format!( + r##" + + + +
+ + + +
+ + + "## + ) + .into() +} + +async fn show_register() -> Html { + format!( + r##" + + + +
+ + + +
+ + + "## + ) + .into() +} + +type AuthSession = axum_login::AuthSession; + +async fn do_register( + app_state: State, + Form(creds): Form, +) -> Result> { + sqlx::query("INSERT INTO users (username, password) VALUES (?, ?)") + .bind(creds.username) + .bind(generate_hash(creds.password)) + .execute(&app_state.db) + .await + .map_err(|err| Html(err.to_string()))?; + + Ok(Redirect::to("/login").into_response()) +} + +async fn do_login( + mut auth_session: AuthSession, + Form(creds): Form, +) -> impl IntoResponse { + let user = match auth_session.authenticate(creds.clone()).await { + Ok(Some(user)) => user, + Ok(None) => return StatusCode::UNAUTHORIZED.into_response(), + Err(_) => return StatusCode::INTERNAL_SERVER_ERROR.into_response(), + }; + + if auth_session.login(&user).await.is_err() { + return StatusCode::INTERNAL_SERVER_ERROR.into_response(); + } + + Redirect::to("/protected").into_response() } diff --git a/nixie-server/src/users/login.rs b/nixie-server/src/users/login.rs deleted file mode 100644 index 9e45694..0000000 --- a/nixie-server/src/users/login.rs +++ /dev/null @@ -1,32 +0,0 @@ -use axum::Form; -use axum::http::StatusCode; -use axum::response::Html; -use axum::response::IntoResponse; -use axum::response::Redirect; -use tera::Context; - -use crate::AuthSession; -use crate::UserCredentials; -use crate::WebResult; -use crate::render_template; - -pub async fn show_login() -> WebResult> { - Ok(render_template("users/login.tera.html", &Context::default()).map(Html)?) -} - -pub async fn do_login( - mut auth_session: AuthSession, - Form(creds): Form, -) -> impl IntoResponse { - let user = match auth_session.authenticate(creds.clone()).await { - Ok(Some(user)) => user, - Ok(None) => return StatusCode::UNAUTHORIZED.into_response(), - Err(_) => return StatusCode::INTERNAL_SERVER_ERROR.into_response(), - }; - - if auth_session.login(&user).await.is_err() { - return StatusCode::INTERNAL_SERVER_ERROR.into_response(); - } - - Redirect::to("/protected").into_response() -} diff --git a/nixie-server/src/users/mod.rs b/nixie-server/src/users/mod.rs deleted file mode 100644 index 18e913b..0000000 --- a/nixie-server/src/users/mod.rs +++ /dev/null @@ -1,53 +0,0 @@ -use axum::Router; -use axum::routing::get; -use axum::routing::post; -use axum_login::AuthUser; -use serde::Deserialize; -use serde::Serialize; -use sqlx::FromRow; - -use crate::AppState; - -mod login; -mod register; - -#[derive(Debug, Clone, Serialize, Deserialize, FromRow)] -pub struct User { - id: i64, - username: String, - password: String, -} - -impl User { - pub fn id(&self) -> i64 { - self.id - } - - pub fn username(&self) -> &str { - &self.username - } - - pub fn password(&self) -> &str { - &self.password - } -} - -impl AuthUser for User { - type Id = i64; - - fn id(&self) -> Self::Id { - self.id - } - - fn session_auth_hash(&self) -> &[u8] { - self.password.as_bytes() - } -} - -pub fn routes() -> Router { - Router::new() - .route("/login", get(login::show_login)) - .route("/login", post(login::do_login)) - .route("/register", get(register::show_register)) - .route("/register", post(register::do_register)) -} diff --git a/nixie-server/src/users/register.rs b/nixie-server/src/users/register.rs deleted file mode 100644 index 82e7fbb..0000000 --- a/nixie-server/src/users/register.rs +++ /dev/null @@ -1,30 +0,0 @@ -use axum::Form; -use axum::extract::State; -use axum::response::Html; -use axum::response::IntoResponse; -use axum::response::Redirect; -use password_auth::generate_hash; -use tera::Context; - -use crate::AppState; -use crate::UserCredentials; -use crate::WebResult; -use crate::render_template; - -pub async fn show_register() -> WebResult> { - Ok(render_template("users/register.tera.html", &Context::default()).map(Html)?) -} - -pub async fn do_register( - app_state: State, - Form(creds): Form, -) -> Result> { - sqlx::query("INSERT INTO users (username, password) VALUES (?, ?)") - .bind(creds.username) - .bind(generate_hash(creds.password)) - .execute(&app_state.db) - .await - .map_err(|err| Html(err.to_string()))?; - - Ok(Redirect::to("/login").into_response()) -} diff --git a/nixie-server/templates/base.tera.html b/nixie-server/templates/base.tera.html deleted file mode 100644 index c0b50f0..0000000 --- a/nixie-server/templates/base.tera.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - {% block head %} - {% block title %}{% endblock title%} - Nixie CI - {% endblock head%} - - - - -
-
- {% block content %}{% endblock content %} -
-
-
-
- {% block footer %} - © Copyright 2026 by Hemera - {% endblock footer %} -
-
- - - diff --git a/nixie-server/templates/inputs.tera.html b/nixie-server/templates/inputs.tera.html deleted file mode 100644 index c05724c..0000000 --- a/nixie-server/templates/inputs.tera.html +++ /dev/null @@ -1,6 +0,0 @@ -{% macro text_input(label, name, id="",type="text") %} -
- - -
-{% endmacro text_input %} diff --git a/nixie-server/templates/protected.tera.html b/nixie-server/templates/protected.tera.html deleted file mode 100644 index 5ed964b..0000000 --- a/nixie-server/templates/protected.tera.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends "base.tera.html" %} - -{% block title %} -Protected Page -{% endblock title %} - -{% block content %} - This is super secret content! -{% endblock content %} diff --git a/nixie-server/templates/users/login.tera.html b/nixie-server/templates/users/login.tera.html deleted file mode 100644 index efd397e..0000000 --- a/nixie-server/templates/users/login.tera.html +++ /dev/null @@ -1,28 +0,0 @@ -{% extends "base.tera.html" %} -{% import "inputs.tera.html" as inputs %} - -{% block title %} -Login -{% endblock title %} - -{% block content %} -
-
-

Login

-
- {{ inputs::text_input(label="Username", name="username", id="username") }} - {{ inputs::text_input(label="Password", name="password", id="password", type="password") }} -
- -
- -
-
-
-{% endblock content %}