From d608cc2d0a2c7dc5d921557e5ddfc4740660fe38 Mon Sep 17 00:00:00 2001 From: Paul Maruhn <paulmaruhn@posteo.de> Date: Wed, 12 May 2021 01:39:11 +0200 Subject: [PATCH] wip and updates and stuff --- Cargo.lock | 636 +++++++++++++++++++++++++++- README.md | 2 +- ffddns-web/Cargo.toml | 5 + ffddns-web/src/db.rs | 32 ++ ffddns-web/src/main.rs | 141 +----- ffddns-web/src/web/dns.rs | 68 +++ ffddns-web/src/web/mod.rs | 215 ++++++++++ ffddns-web/templates/head.html | 9 + ffddns-web/templates/index.html | 7 + ffddns-web/templates/navbar.html | 40 ++ ffddns-web/templates/newdomain.html | 33 ++ ffddns-web/templates/node.html | 15 + ffddns-web/templates/nodelist.html | 32 ++ 13 files changed, 1087 insertions(+), 148 deletions(-) create mode 100644 ffddns-web/src/web/dns.rs create mode 100644 ffddns-web/src/web/mod.rs create mode 100644 ffddns-web/templates/head.html create mode 100644 ffddns-web/templates/index.html create mode 100644 ffddns-web/templates/navbar.html create mode 100644 ffddns-web/templates/newdomain.html create mode 100644 ffddns-web/templates/node.html create mode 100644 ffddns-web/templates/nodelist.html diff --git a/Cargo.lock b/Cargo.lock index 09c1329..41452ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "aead" version = "0.2.0" @@ -55,6 +57,15 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + [[package]] name = "atty" version = "0.2.14" @@ -63,7 +74,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -124,6 +135,15 @@ dependencies = [ "byte-tools", ] +[[package]] +name = "bstr" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d" +dependencies = [ + "memchr", +] + [[package]] name = "byte-tools" version = "0.3.1" @@ -158,7 +178,17 @@ dependencies = [ "num-integer", "num-traits", "time", - "winapi", + "winapi 0.3.9", +] + +[[package]] +name = "chrono-tz" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2554a3155fec064362507487171dcc4edc3df60cb10f3a1fb10ed8094822b120" +dependencies = [ + "chrono", + "parse-zoneinfo", ] [[package]] @@ -177,6 +207,17 @@ dependencies = [ "time", ] +[[package]] +name = "crossbeam-utils" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" +dependencies = [ + "autocfg", + "cfg-if 1.0.0", + "lazy_static", +] + [[package]] name = "crypto-mac" version = "0.7.0" @@ -187,6 +228,12 @@ dependencies = [ "subtle 1.0.0", ] +[[package]] +name = "deunicode" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690" + [[package]] name = "devise" version = "0.2.0" @@ -204,7 +251,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "066ceb7928ca93a9bedc6d0e612a8a0424048b0ab1f75971b203d01420c055d7" dependencies = [ "devise_core", - "quote", + "quote 0.6.13", ] [[package]] @@ -214,9 +261,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf41c59b22b5e3ec0ea55c7847e5f358d340f3a8d6d53a5cf4f1564967f96487" dependencies = [ "bitflags", - "proc-macro2", - "quote", - "syn", + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", ] [[package]] @@ -251,11 +298,69 @@ name = "ffddns-web" version = "0.1.0" dependencies = [ "chrono", + "log 0.4.14", "rand 0.8.3", "rocket", + "rocket_contrib", "rusqlite", + "serde", + "serde_json", + "tera", ] +[[package]] +name = "filetime" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall", + "winapi 0.3.9", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fsevent" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" +dependencies = [ + "bitflags", + "fsevent-sys", +] + +[[package]] +name = "fsevent-sys" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" +dependencies = [ + "libc", +] + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + [[package]] name = "generic-array" version = "0.12.3" @@ -302,6 +407,30 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "globset" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c152169ef1e421390738366d2f796655fec62621dabbd0fd476f905934061e4a" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log 0.4.14", + "regex", +] + +[[package]] +name = "globwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +dependencies = [ + "bitflags", + "ignore", + "walkdir", +] + [[package]] name = "hashbrown" version = "0.9.1" @@ -343,6 +472,12 @@ version = "1.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "615caabe2c3160b313d52ccc905335f4ed5f10881dd63dc5699d47e90be85691" +[[package]] +name = "humansize" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e" + [[package]] name = "hyper" version = "0.10.16" @@ -373,6 +508,24 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "ignore" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b287fb45c60bb826a0dc68ff08742b9d88a2fea13d6e0c286b3172065aaf878c" +dependencies = [ + "crossbeam-utils", + "globset", + "lazy_static", + "log 0.4.14", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + [[package]] name = "indexmap" version = "1.6.1" @@ -383,18 +536,69 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "inotify" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f" +dependencies = [ + "bitflags", + "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 = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + [[package]] name = "itoa" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "language-tags" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.86" @@ -444,6 +648,12 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + [[package]] name = "matches" version = "0.1.8" @@ -465,6 +675,78 @@ dependencies = [ "log 0.3.9", ] +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log 0.4.14", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + +[[package]] +name = "mio-extras" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" +dependencies = [ + "lazycell", + "log 0.4.14", + "mio", + "slab", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + +[[package]] +name = "net2" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "notify" +version = "4.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2599080e87c9bd051ddb11b10074f4da7b1223298df65d4c2ec5bcf309af1533" +dependencies = [ + "bitflags", + "filetime", + "fsevent", + "fsevent-sys", + "inotify", + "libc", + "mio", + "mio-extras", + "walkdir", + "winapi 0.3.9", +] + [[package]] name = "num-integer" version = "0.1.44" @@ -494,12 +776,27 @@ dependencies = [ "libc", ] +[[package]] +name = "once_cell" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" + [[package]] name = "opaque-debug" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +[[package]] +name = "parse-zoneinfo" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" +dependencies = [ + "regex", +] + [[package]] name = "pear" version = "0.1.4" @@ -515,9 +812,9 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfc1c836fdc3d1ef87c348b237b5b5c4dff922156fb2d968f57734f9669768ca" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", "version_check 0.9.2", "yansi", ] @@ -534,6 +831,49 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "pest" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +dependencies = [ + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2 1.0.24", + "quote 1.0.9", + "syn 1.0.61", +] + +[[package]] +name = "pest_meta" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +dependencies = [ + "maplit", + "pest", + "sha-1", +] + [[package]] name = "pkg-config" version = "0.3.19" @@ -562,7 +902,16 @@ version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" dependencies = [ - "unicode-xid", + "unicode-xid 0.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +dependencies = [ + "unicode-xid 0.2.1", ] [[package]] @@ -571,7 +920,16 @@ version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" dependencies = [ - "proc-macro2", + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2 1.0.24", ] [[package]] @@ -655,6 +1013,33 @@ dependencies = [ "rand_core 0.6.1", ] +[[package]] +name = "redox_syscall" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" + [[package]] name = "rocket" version = "0.4.7" @@ -685,12 +1070,25 @@ dependencies = [ "devise", "glob", "indexmap", - "quote", + "quote 0.6.13", "rocket_http", "version_check 0.9.2", "yansi", ] +[[package]] +name = "rocket_contrib" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7954a707f9ca18aa74ca8c1f5d1f900f52a4dceb68e96e3112143f759cfd20e" +dependencies = [ + "log 0.4.14", + "notify", + "rocket", + "serde", + "serde_json", +] + [[package]] name = "rocket_http" version = "0.4.7" @@ -705,7 +1103,7 @@ dependencies = [ "smallvec", "state", "time", - "unicode-xid", + "unicode-xid 0.1.0", ] [[package]] @@ -737,23 +1135,58 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "serde" -version = "1.0.123" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae" +checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.9", + "syn 1.0.61", +] [[package]] name = "serde_json" -version = "1.0.62" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486" +checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" dependencies = [ "itoa", "ryu", "serde", ] +[[package]] +name = "sha-1" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +dependencies = [ + "block-buffer", + "digest", + "fake-simd", + "opaque-debug", +] + [[package]] name = "sha2" version = "0.8.2" @@ -766,6 +1199,21 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "slab" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" + +[[package]] +name = "slug" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373" +dependencies = [ + "deunicode", +] + [[package]] name = "smallvec" version = "1.6.1" @@ -796,9 +1244,51 @@ version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] + +[[package]] +name = "syn" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed22b90a0e734a23a7610f4283ac9e5acfb96cbb30dfefa540d66f866f1c09c5" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.9", + "unicode-xid 0.2.1", +] + +[[package]] +name = "tera" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac6ab7eacf40937241959d540670f06209c38ceadb62116999db4a950fbf8dc" +dependencies = [ + "chrono", + "chrono-tz", + "globwalk", + "humansize", + "lazy_static", + "percent-encoding 2.1.0", + "pest", + "pest_derive", + "rand 0.8.3", + "regex", + "serde", + "serde_json", + "slug", + "unic-segment", +] + +[[package]] +name = "thread_local" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +dependencies = [ + "once_cell", ] [[package]] @@ -809,7 +1299,7 @@ checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -854,6 +1344,62 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +[[package]] +name = "ucd-trie" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" + +[[package]] +name = "unic-char-property" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +dependencies = [ + "unic-char-range", +] + +[[package]] +name = "unic-char-range" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" + +[[package]] +name = "unic-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" + +[[package]] +name = "unic-segment" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23" +dependencies = [ + "unic-ucd-segment", +] + +[[package]] +name = "unic-ucd-segment" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-version" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +dependencies = [ + "unic-common", +] + [[package]] name = "unicase" version = "1.4.2" @@ -887,6 +1433,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + [[package]] name = "universal-hash" version = "0.3.0" @@ -926,6 +1478,17 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +[[package]] +name = "walkdir" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" +dependencies = [ + "same-file", + "winapi 0.3.9", + "winapi-util", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -938,6 +1501,12 @@ version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -948,18 +1517,43 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "yansi" version = "0.5.0" diff --git a/README.md b/README.md index 605bc9c..c487aa3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# FFDDNS +# FFdynDNS Freifunk dynamic DNS Service diff --git a/ffddns-web/Cargo.toml b/ffddns-web/Cargo.toml index 50459fd..41e6fdd 100644 --- a/ffddns-web/Cargo.toml +++ b/ffddns-web/Cargo.toml @@ -8,6 +8,11 @@ edition = "2018" [dependencies] rocket = "0.4.7" +rocket_contrib = "*" rusqlite = {version = "0.21", features = ["chrono", "serde_json"]} chrono = "0.4.19" rand = "0.8.3" +tera = "1.6.1" +log = "*" +serde_json = "1.0.64" +serde = {version = "1.0.125", features = ["derive"]} diff --git a/ffddns-web/src/db.rs b/ffddns-web/src/db.rs index 27c7f17..494d562 100644 --- a/ffddns-web/src/db.rs +++ b/ffddns-web/src/db.rs @@ -102,3 +102,35 @@ impl Domain { } } } + +impl Domain { + pub fn new_with_token(domain: String, token: String) -> Self { + Self { + domainname: domain, + token: token, + lastupdate: None, + ipv4: None, + ipv6: None + } + } + + /// creates a new Domain object and generates a random token + pub fn new(domain: String) -> Self { + Self { + domainname: domain, + token: generate_token(), + lastupdate: None, + ipv4: None, + ipv6: None + } + } +} + + +pub fn generate_token() -> String { + let mut token = String::new(); + for _ in 0..8 { + token.push_str(&format!("{:02x}", rand::random::<u8>())); + } + token +} diff --git a/ffddns-web/src/main.rs b/ffddns-web/src/main.rs index b7f3c69..4435386 100644 --- a/ffddns-web/src/main.rs +++ b/ffddns-web/src/main.rs @@ -1,59 +1,25 @@ #![feature(proc_macro_hygiene, decl_macro)] mod db; -use chrono::{DateTime, Utc}; -use db::{ - Database, - Domain, -}; -use rocket::{ - self, - get, - post, - routes, - State, -}; -use rocket::request::{ - Request, - FromRequest, - Outcome, -}; +mod web; + +use chrono::DateTime; +use chrono::Utc; +use crate::db::Database; +use crate::db::Domain; +use rocket; +use rocket::get; +use rocket::post; +use rocket::routes; +use rocket::State; +use rocket::request::Request; +use rocket::request::FromRequest; +use rocket::request::Outcome; use std::fmt::{self, Display}; use std::net::IpAddr; use rand; -pub struct ClientIp(IpAddr); - - -impl ClientIp { - pub fn inner(&self) -> &IpAddr { - let ClientIp(ip) = self; - ip - } - pub fn into_inner(self) -> IpAddr { - let ClientIp(ip) = self; - ip - } -} - - -impl Display for ClientIp { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.inner().to_string()) - } -} - - -impl<'a, 'r> FromRequest<'a, 'r> for ClientIp { - type Error = String; - - fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> { - let ip = request.client_ip().unwrap(); - Outcome::Success(ClientIp(ip)) - } -} - #[derive(Debug, Clone)] pub struct DomainUpdate { @@ -62,84 +28,7 @@ pub struct DomainUpdate { } -#[get("/update?<token>&<domain>&<ip>")] -fn update(db: State<Database>, clientip: ClientIp, token: String, domain: String, ip: Option<String>) -> String { - let new_ip: IpAddr = { - if let Some(iip) = ip { - iip.parse::<IpAddr>().unwrap() - } - else { - clientip.into_inner() - } - }; - - let d = db.get_domain(&domain).unwrap(); - - if d.token != token { - return "not a valid token".to_string(); - } - - match new_ip { - IpAddr::V4(addr) => db.update_ipv4(&domain, addr), - IpAddr::V6(addr) => db.update_ipv6(&domain, addr), - } - - db.update_lastupdate(&domain, Utc::now()); - - format!("{} updated to {:?}", domain, new_ip) -} - - -#[get("/create?<domain>")] -fn create(db: State<Database>, domain: String) -> String { - let token = generate_token(); - let d = Domain { - domainname: domain.clone(), - token: token.clone(), - lastupdate: None, - ipv4: None, - ipv6: None - }; - - db.insert_new_domain(&d); - - format!("your token for {}: {}", domain, token) -} - - -#[get("/status?<domain>")] -fn status(db: State<Database>, domain: String) -> String { - let domaininfo = match db.get_domain(&domain) { - None => return "domain not found".to_string(), - Some(r) => r, - }; - - format!("{:#?}", domaininfo) -} - - - fn main() { let db = db::Database::new("./ffddns.sqlite".into()); - - rocket::ignite() - .mount("/", routes![ - update, - create, - status - ]) - .manage(db) - .launch(); -} - - - -fn generate_token() -> String { - let mut token = String::new(); - - for _ in 0..8 { - token.push_str(&format!("{:02x}", rand::random::<u8>())); - } - - token + web::start_web(db); } diff --git a/ffddns-web/src/web/dns.rs b/ffddns-web/src/web/dns.rs new file mode 100644 index 0000000..604bd1a --- /dev/null +++ b/ffddns-web/src/web/dns.rs @@ -0,0 +1,68 @@ +use log::{error, info, debug}; +use tera::{self}; + +use crate::db::Database; +use crate::db::Domain; +use chrono::DateTime; +use chrono::Utc; +use rand; +use rocket; +use rocket::get; +use rocket::post; +use rocket::request::FromRequest; +use rocket::request::Outcome; +use rocket::request::Request; +use rocket::response::content; +use rocket::response::content::Html; +use rocket::routes; +use rocket::State; +use serde_json as json; +use serde_json::json; +use serde::{Serialize, Deserialize}; +use std::fmt::{self, Display}; +use std::net::IpAddr; +use super::AppState; +use rocket_contrib::json::Json; + +#[derive(Clone, Debug, Serialize)] +pub enum QType { + A, + AAAA, + SOA, +} + +#[derive(Clone, Debug, Serialize)] +pub struct DnsResponse { + result: Vec<DnsRecord> +} + +#[derive(Clone, Debug, Serialize)] +pub struct DnsRecord { + // AAAA + qtype: QType, + // www.example.com + qname: String, + // 203.0.113.2 + content: String, + // 60 + ttl: usize +} + +#[get("/lookup/<domain>/<record>")] +pub fn lookup(state: State<AppState>, domain: String, record: String) -> Json<DnsResponse> { + info!("{:?} {:?}", record, domain); + let res = DnsResponse { + result: vec![ + DnsRecord { + qtype: QType::A, + qname: "ffhl.de.".to_string(), + content: "1.1.1.1".to_string(), + ttl: 60 + } + ] + }; + + info!("{:#?}", res); + + Json(res) +} diff --git a/ffddns-web/src/web/mod.rs b/ffddns-web/src/web/mod.rs new file mode 100644 index 0000000..545998c --- /dev/null +++ b/ffddns-web/src/web/mod.rs @@ -0,0 +1,215 @@ +mod dns; + +use log::{error, info}; +use tera::{self}; + +use crate::db::{self, Database, Domain}; +use chrono::DateTime; +use chrono::Utc; +use rand; +use rocket; +use rocket::get; +use rocket::post; +use rocket::request::FromRequest; +use rocket::request::Outcome; +use rocket::request::Request; +use rocket::response::content; +use rocket::response::content::Html; +use rocket::routes; +use rocket::State; +use serde_json as json; +use serde_json::json; +use std::fmt::{self, Display}; +use std::net::IpAddr; +use tera::Tera; + +const TEMPLATES: &[(&str, &str)] = &[ + ("index", include_str!("../../templates/index.html")), + ("nodelist", include_str!("../../templates/nodelist.html")), + ("head", include_str!("../../templates/head.html")), + ("node", include_str!("../../templates/node.html")), + ("navbar", include_str!("../../templates/navbar.html")), + ("newdomain", include_str!("../../templates/newdomain.html")), +]; + +pub struct AppState { + templates: Tera, + db: Database, +} + +pub struct ClientIp(IpAddr); + +impl ClientIp { + pub fn inner(&self) -> &IpAddr { + let ClientIp(ip) = self; + ip + } + + pub fn into_inner(self) -> IpAddr { + let ClientIp(ip) = self; + ip + } +} + +impl Display for ClientIp { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.inner().to_string()) + } +} + +impl<'a, 'r> FromRequest<'a, 'r> for ClientIp { + type Error = String; + + fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> { + let ip = request.client_ip().unwrap(); + Outcome::Success(ClientIp(ip)) + } +} + +#[get("/update?<token>&<domain>&<ip>")] +fn update( + db: State<Database>, + clientip: ClientIp, + token: String, + domain: String, + ip: Option<String>, +) -> String { + let new_ip: IpAddr = { + if let Some(iip) = ip { + iip.parse::<IpAddr>().unwrap() + } else { + clientip.into_inner() + } + }; + + let d = db.get_domain(&domain).unwrap(); + + if d.token != token { + return "not a valid token".to_string(); + } + + match new_ip { + IpAddr::V4(addr) => db.update_ipv4(&domain, addr), + IpAddr::V6(addr) => db.update_ipv6(&domain, addr), + } + + db.update_lastupdate(&domain, Utc::now()); + + format!("{} updated to {:?}", domain, new_ip) +} + +#[get("/create?<domain>")] +fn create(db: State<Database>, domain: String) -> String { + let token = db::generate_token(); + let d = Domain { + domainname: domain.clone(), + token: token.clone(), + lastupdate: None, + ipv4: None, + ipv6: None, + }; + + db.insert_new_domain(&d); + + format!("your token for {}: {}", domain, token) +} + +#[get("/status?<domain>")] +fn status(db: State<Database>, domain: String) -> String { + let domaininfo = match db.get_domain(&domain) { + None => return "domain not found".to_string(), + Some(r) => r, + }; + + format!("{:#?}", domaininfo) +} + +#[get("/")] +fn index(state: State<'_, AppState>) -> Html<String> { + let html = state + .templates + .render("index", &tera::Context::from_serialize(&json!({})).unwrap()) + .unwrap(); + + Html(html) +} + +#[get("/newdomain?<domainname>")] +fn newdomain(state: State<'_, AppState>, domainname: Option<String>) -> Html<String> { + let db = &state.db; + let mut template_data: json::Value = json!({}); + + match &domainname { + Some(name) if db.get_domain(&name).is_some() => { + template_data = json!({ + "form_request": true, + "created": false, + "error": true, + "error_msg": "Domain already exists" + }) + } + Some(name) if db.get_domain(&name).is_none() => { + let domain = db::Domain::new(name.clone()); + db.insert_new_domain(&domain); + + template_data = json!({ + "form_request": true, + "created": true, + "error": false, + "token": domain.token + }); + } + None | _ => { + template_data = json!({ + "form_request": false + }) + } + } + + + + let html = state + .templates + .render( + "newdomain", + &tera::Context::from_serialize(&template_data).unwrap() + ).unwrap(); + + info!("{:#?}", domainname); + + Html(html) +} + +pub fn start_web(db: Database) { + let appstate = AppState { + db: db, + templates: load_templates(), + }; + + rocket::custom(rocket::config::ConfigBuilder::new(rocket::config::Environment::Development) + .port(8053) + .finalize() + .unwrap() + ) + .mount("/", routes![index, update, create, status, newdomain]) + .mount("/dns", routes![dns::lookup]) + .manage(appstate) + .launch(); +} + +fn load_templates() -> tera::Tera { + let mut t = tera::Tera::default(); + + for (name, template) in TEMPLATES { + if let Err(e) = t.add_raw_template(name, template) { + error!("failed to load template: {}", name); + match &e.kind { + tera::ErrorKind::Msg(m) => error!("{}", m), + _ => error!("unknown error"), + } + panic!("loading templates failed: {:#?}", e); + } + } + + t +} diff --git a/ffddns-web/templates/head.html b/ffddns-web/templates/head.html new file mode 100644 index 0000000..0ddf38e --- /dev/null +++ b/ffddns-web/templates/head.html @@ -0,0 +1,9 @@ +<!doctype html> +<head> + <Title>{{ site.title | default (value="FFdynDNS") }} </Title> + <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" + integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous"> + <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js" + integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" + crossorigin="anonymous"></script> +</head> diff --git a/ffddns-web/templates/index.html b/ffddns-web/templates/index.html new file mode 100644 index 0000000..d89caef --- /dev/null +++ b/ffddns-web/templates/index.html @@ -0,0 +1,7 @@ +{% include "head" %} +<body> + {% include "navbar" %} + <div class="container"> + <p>Hello Freifunk!</p> + </div> +</body> diff --git a/ffddns-web/templates/navbar.html b/ffddns-web/templates/navbar.html new file mode 100644 index 0000000..342ff82 --- /dev/null +++ b/ffddns-web/templates/navbar.html @@ -0,0 +1,40 @@ +<nav class="navbar navbar-expand-lg navbar-light bg-light"> + <div class="container-fluid"> + <a class="navbar-brand" href="/">FFdynDNS</a> + <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" + aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> + <span class="navbar-toggler-icon"></span> + </button> + <div class="collapse navbar-collapse" id="navbarSupportedContent"> + <ul class="navbar-nav me-auto mb-2 mb-lg-0"> + <li class="nav-item"> + <a class="nav-link active" aria-current="page" href="/newdomain">New Domain</a> + </li> + <li class="nav-item"> + <a class="nav-link" href="#">Link</a> + </li> + <li class="nav-item dropdown"> + <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" + data-bs-toggle="dropdown" aria-expanded="false"> + Dropdown + </a> + <ul class="dropdown-menu" aria-labelledby="navbarDropdown"> + <li><a class="dropdown-item" href="#">Action</a></li> + <li><a class="dropdown-item" href="#">Another action</a></li> + <li> + <hr class="dropdown-divider"> + </li> + <li><a class="dropdown-item" href="#">Something else here</a></li> + </ul> + </li> + <li class="nav-item"> + <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a> + </li> + </ul> + <form class="d-flex"> + <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"> + <button class="btn btn-outline-success" type="submit">Search</button> + </form> + </div> + </div> +</nav> diff --git a/ffddns-web/templates/newdomain.html b/ffddns-web/templates/newdomain.html new file mode 100644 index 0000000..2e49990 --- /dev/null +++ b/ffddns-web/templates/newdomain.html @@ -0,0 +1,33 @@ +{% include "head" %} + +<body> + {% include "navbar" %} + <div class="container"> + <h1>Create a new Domain</h1> + {% if error %} + <div class="alert alert-danger" role="alert"> + {{ error_msg }} + </div> + {% endif %} + {% if not form_request %} + <form action="/newdomain" method="GET"> + <div class="mb-3"> + <label for="domainname" class="form-label">Domain name</label> + <input type="text" class="form-control" id="domainname" name="domainname" required aria-describedby="domainnameHelp"> + <div id="domainnameHelp" class="form-text">Your domain name</div> + </div> + <div class="mb-3 form-check"> + <input type="checkbox" class="form-check-input" id="exampleCheck1"> + <label class="form-check-label" for="exampleCheck1">Check me out</label> + </div> + <button type="submit" class="btn btn-primary">Submit</button> + </form> + {% endif %} + {% if form_request and created %} + <div class="alert alert-success" role="alert"> + Your domain was successfully created! <br> + Your token is: <span class="badge bg-light text-dark">{{ token }}</span> + </div> + {% endif %} + </div> +</body> diff --git a/ffddns-web/templates/node.html b/ffddns-web/templates/node.html new file mode 100644 index 0000000..eb68a43 --- /dev/null +++ b/ffddns-web/templates/node.html @@ -0,0 +1,15 @@ +{% include "head" %} + +<body> + {% include "navbar" %} + <div class="container"> + + <h1>{{ node.last_response.nodeinfo.hostname }}</h1> + node is {{ node.status }} <br> + last response {{ last_response_secs }} ago <br> + + <textarea readonly style="width: 90%; height: 1200px; font-family: monospace;"> +{{ last_response }} + </textarea> + </div> +</body> diff --git a/ffddns-web/templates/nodelist.html b/ffddns-web/templates/nodelist.html new file mode 100644 index 0000000..a8b83e5 --- /dev/null +++ b/ffddns-web/templates/nodelist.html @@ -0,0 +1,32 @@ +{% include "head" %} +<body> + {% include "navbar" %} + <div class="container"> + + <h1 id="content" class="bd-title">Nodelist</h1> + <table class="table table-striped"> + <thead> + <tr> + <th scope="col">Hostname</th> + <th scope="col">Status</th> + <th scope="col">last response</th> + <th scope="col">Address</th> + </tr> + </thead> + {% for node in nodes %} + <tr> + <th><a href="/node/{{ node.nodeid }}">{{ node.last_response.nodeinfo.hostname }}</a></th> + <th> + {% if node.status == "Up" %} + <span class="badge bg-success">Up</span> + {% else %} + <span class="badge bg-danger">Down</span> + {% endif %} + </th> + <th>{{ node.last_seen_secs }}s ago</th> + <th><a href="http://[{{ node.last_address }}]">{{ node.last_address }}</a></th> + </tr> + {% endfor %} + </table> + </div> +</body> -- GitLab