wip frontend
This commit is contained in:
parent
806d57379a
commit
c04090adaf
21 changed files with 747 additions and 58 deletions
307
Cargo.lock
generated
307
Cargo.lock
generated
|
@ -8,7 +8,7 @@ version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
|
checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"generic-array 0.14.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -20,7 +20,7 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cipher",
|
"cipher",
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
"opaque-debug",
|
"opaque-debug 0.3.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -37,6 +37,15 @@ dependencies = [
|
||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "0.7.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ansi_term"
|
name = "ansi_term"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
|
@ -145,7 +154,19 @@ version = "0.10.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b9cf849ee05b2ee5fba5e36f97ff8ec2533916700fc0758d40d92136a42f3388"
|
checksum = "b9cf849ee05b2ee5fba5e36f97ff8ec2533916700fc0758d40d92136a42f3388"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"digest",
|
"digest 0.10.3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
|
||||||
|
dependencies = [
|
||||||
|
"block-padding",
|
||||||
|
"byte-tools",
|
||||||
|
"byteorder",
|
||||||
|
"generic-array 0.12.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -154,9 +175,33 @@ version = "0.10.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
|
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"generic-array 0.14.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-padding"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
|
||||||
|
dependencies = [
|
||||||
|
"byte-tools",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bstr"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byte-tools"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
|
@ -201,7 +246,7 @@ version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
|
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"generic-array 0.14.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -270,13 +315,23 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
|
checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"generic-array 0.14.5",
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -374,13 +429,22 @@ dependencies = [
|
||||||
"migrations_macros",
|
"migrations_macros",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array 0.12.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.10.3"
|
version = "0.10.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
|
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
"block-buffer 0.10.2",
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
@ -418,6 +482,12 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fake-simd"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "1.7.0"
|
version = "1.7.0"
|
||||||
|
@ -550,6 +620,15 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.12.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.5"
|
version = "0.14.5"
|
||||||
|
@ -577,7 +656,7 @@ version = "0.4.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99"
|
checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"opaque-debug",
|
"opaque-debug 0.3.0",
|
||||||
"polyval",
|
"polyval",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -587,6 +666,30 @@ version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "globset"
|
||||||
|
version = "0.4.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"bstr",
|
||||||
|
"fnv",
|
||||||
|
"log",
|
||||||
|
"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]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
|
@ -623,7 +726,7 @@ version = "0.12.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"digest",
|
"digest 0.10.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -700,6 +803,24 @@ dependencies = [
|
||||||
"unicode-normalization",
|
"unicode-normalization",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ignore"
|
||||||
|
version = "0.4.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
"globset",
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"memchr",
|
||||||
|
"regex",
|
||||||
|
"same-file",
|
||||||
|
"thread_local",
|
||||||
|
"walkdir",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.8.1"
|
version = "1.8.1"
|
||||||
|
@ -794,6 +915,12 @@ dependencies = [
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "maplit"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matchers"
|
name = "matchers"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -913,6 +1040,7 @@ dependencies = [
|
||||||
"rocket_sync_db_pools",
|
"rocket_sync_db_pools",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"tera",
|
||||||
"time 0.3.9",
|
"time 0.3.9",
|
||||||
"tokio",
|
"tokio",
|
||||||
"trust-dns-client",
|
"trust-dns-client",
|
||||||
|
@ -973,6 +1101,12 @@ version = "1.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
|
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "opaque-debug"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opaque-debug"
|
name = "opaque-debug"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
@ -1100,6 +1234,49 @@ version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
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",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
|
@ -1126,7 +1303,7 @@ checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
"opaque-debug",
|
"opaque-debug 0.3.0",
|
||||||
"universal-hash",
|
"universal-hash",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1277,6 +1454,8 @@ version = "1.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
|
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
"regex-syntax",
|
"regex-syntax",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1416,6 +1595,15 @@ version = "1.0.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "same-file"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scheduled-thread-pool"
|
name = "scheduled-thread-pool"
|
||||||
version = "0.2.5"
|
version = "0.2.5"
|
||||||
|
@ -1468,6 +1656,18 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha-1"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer 0.7.3",
|
||||||
|
"digest 0.8.1",
|
||||||
|
"fake-simd",
|
||||||
|
"opaque-debug 0.2.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.10.2"
|
version = "0.10.2"
|
||||||
|
@ -1476,7 +1676,7 @@ checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
"digest",
|
"digest 0.10.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1580,6 +1780,22 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tera"
|
||||||
|
version = "1.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3cac831b615c25bcef632d1cabf864fa05813baad3d526829db18eb70e8b58d"
|
||||||
|
dependencies = [
|
||||||
|
"globwalk",
|
||||||
|
"lazy_static",
|
||||||
|
"pest",
|
||||||
|
"pest_derive",
|
||||||
|
"regex",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"unic-segment",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
@ -1880,6 +2096,12 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ucd-trie"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uncased"
|
name = "uncased"
|
||||||
version = "0.9.6"
|
version = "0.9.6"
|
||||||
|
@ -1890,6 +2112,56 @@ dependencies = [
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[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]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
|
@ -1917,7 +2189,7 @@ version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
|
checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"generic-array 0.14.5",
|
||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1961,6 +2233,17 @@ version = "0.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "walkdir"
|
||||||
|
version = "2.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
|
||||||
|
dependencies = [
|
||||||
|
"same-file",
|
||||||
|
"winapi",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "want"
|
name = "want"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
|
|
@ -25,6 +25,7 @@ figment = { version = "0.10.6", features = ["toml", "env"] }
|
||||||
clap = {version = "3", features = ["derive", "cargo"]}
|
clap = {version = "3", features = ["derive", "cargo"]}
|
||||||
argon2 = {version = "0.4", default-features = false, features = ["alloc", "password-hash"] }
|
argon2 = {version = "0.4", default-features = false, features = ["alloc", "password-hash"] }
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
tera = {version = "1", default-features = false}
|
||||||
# From trust-dns-client
|
# From trust-dns-client
|
||||||
futures-util = { version = "0.3.5", default-features = false, features = ["std"] }
|
futures-util = { version = "0.3.5", default-features = false, features = ["std"] }
|
||||||
# From rocket / cookie-rs
|
# From rocket / cookie-rs
|
||||||
|
|
22
public/scripts/api.js
Normal file
22
public/scripts/api.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
const baseUrl = '/api/v1';
|
||||||
|
|
||||||
|
|
||||||
|
function apiGet(url) {
|
||||||
|
return fetch(`${baseUrl}/${url}`)
|
||||||
|
.then(res => {
|
||||||
|
if (!res.ok) {
|
||||||
|
// do something here
|
||||||
|
throw new Error('Not ok');
|
||||||
|
}
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getRecords(zone) {
|
||||||
|
return apiGet(`zones/${zone}/records`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
getRecords,
|
||||||
|
};
|
100
public/scripts/records.js
Normal file
100
public/scripts/records.js
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
import { html, Component, render, createContext, useState, useEffect } from 'https://unpkg.com/htm/preact/standalone.mjs';
|
||||||
|
import { getRecords } from './api.js';
|
||||||
|
|
||||||
|
const rdataInputProperties = {
|
||||||
|
Address: {label: 'adresse', type: 'text'},
|
||||||
|
Serial: {label: 'serial', type: 'number'},
|
||||||
|
Minimum: {label: 'minimum', type: 'number'},
|
||||||
|
Retry: {label: 'nouvelle tentative', type: 'number'},
|
||||||
|
Refresh: {label: 'actualisation', type: 'number'},
|
||||||
|
MaintainerName: {label: 'contact', type: 'text'},
|
||||||
|
MasterServerName: {label: 'serveur primaire', type: 'text'},
|
||||||
|
Expire: {label: 'expiration', type: 'number'},
|
||||||
|
Target: {label: 'cible', type: 'text'},
|
||||||
|
}
|
||||||
|
|
||||||
|
const Editable = createContext(false);
|
||||||
|
|
||||||
|
|
||||||
|
function RDataInput({ name, value = '', index = 0 }) {
|
||||||
|
const {label, type} = rdataInputProperties[name] || {label: name, type: 'text'};
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<${Editable.Consumer}>
|
||||||
|
${
|
||||||
|
(editable) => {
|
||||||
|
if (editable) {
|
||||||
|
return html`
|
||||||
|
<div>
|
||||||
|
<label for=record_${index}_${name}>${label}:</label>
|
||||||
|
<input id=record_${index}_${name} type=${type} value=${value} />
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
return html`
|
||||||
|
<div>
|
||||||
|
<span class=label>${label}:</span>
|
||||||
|
<span class=value>${value}</span>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<//>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function RData({ rdata, index }) {
|
||||||
|
const { Address: address } = rdata;
|
||||||
|
return Object.entries(rdata).map(([name, value]) => html`<${RDataInput} name=${name} value=${value} index=${index} />`);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function Record({name, ttl, type, rdata, index = 0}) {
|
||||||
|
return html`
|
||||||
|
<tr>
|
||||||
|
<td class=domain>${name}</div>
|
||||||
|
<td class=type>${type}</div>
|
||||||
|
<td class=ttl>${ttl}</div>
|
||||||
|
<td class=rdata><${RData} rdata=${rdata} index=${index}/></div>
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function RecordList({ zone }) {
|
||||||
|
const [records, setRecords] = useState([]);
|
||||||
|
const [editable, setEditable] = useState(false);
|
||||||
|
|
||||||
|
const toggleEdit = () => setEditable(!editable);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getRecords(zone)
|
||||||
|
.then((res) => setRecords(res));
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<${Editable.Provider} value=${editable}>
|
||||||
|
<button onclick=${toggleEdit}>${ editable ? 'Save' : 'Edit'}</button>
|
||||||
|
<table class=record-list>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Nom</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>TTL</th>
|
||||||
|
<th>Données</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
${records.map(
|
||||||
|
({Name, Class, TTL, Type, ...rdata}, index) => {
|
||||||
|
return html`<${Record} name=${Name} ttl=${TTL} type=${Type} rdata=${rdata} index=${index}/>`
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</ul>
|
||||||
|
<//>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { RecordList };
|
41
public/styles/main.css
Normal file
41
public/styles/main.css
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
body {
|
||||||
|
color: #2e2033;
|
||||||
|
}
|
||||||
|
.record-list {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-list .rdata {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-list th, .record-list td {
|
||||||
|
font-weight: normal;
|
||||||
|
text-align: left;
|
||||||
|
vertical-align: top;
|
||||||
|
padding: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-list thead {
|
||||||
|
background: #ccb9ff;
|
||||||
|
color: #39004d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-list tbody tr:nth-child(even) td {
|
||||||
|
background: #ccb9ff3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-list tbody tr .rdata span.label,
|
||||||
|
.record-list tbody tr .rdata label {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.1em 0.5em;
|
||||||
|
background: #cecece;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
margin-right: 0.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-list tbody tr .rdata > div {
|
||||||
|
margin: 0.1rem 0.5rem 0.1rem 0;
|
||||||
|
}
|
|
@ -4,13 +4,15 @@ use std::process::exit;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use rocket::{Rocket, Build};
|
use rocket::{Rocket, Build};
|
||||||
use rocket::fairing::AdHoc;
|
use rocket::fairing::AdHoc;
|
||||||
|
use rocket::fs::FileServer;
|
||||||
use figment::Figment;
|
use figment::Figment;
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::routes::users::*;
|
use crate::routes::api;
|
||||||
use crate::routes::zones::*;
|
use crate::routes::ui;
|
||||||
use crate::{DbConn, get_db_conn};
|
use crate::{DbConn, get_db_conn};
|
||||||
use crate::cli::NomiloCommand;
|
use crate::cli::NomiloCommand;
|
||||||
|
use crate::template::TemplateState;
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
pub enum ServerCommand {
|
pub enum ServerCommand {
|
||||||
|
@ -78,21 +80,31 @@ impl NomiloCommand for RunServerCommand {
|
||||||
if let Some(port) = self.port {
|
if let Some(port) = self.port {
|
||||||
figment = figment.merge(("port", port));
|
figment = figment.merge(("port", port));
|
||||||
}
|
}
|
||||||
|
let template_state = TemplateState::new(&app_config.web_app.templates_directory);
|
||||||
|
let static_files = FileServer::from(&app_config.web_app.static_files);
|
||||||
|
|
||||||
let _res = rocket::custom(figment)
|
let _res = rocket::custom(figment)
|
||||||
.manage(app_config)
|
.manage(app_config)
|
||||||
|
.manage(template_state)
|
||||||
.attach(DbConn::fairing())
|
.attach(DbConn::fairing())
|
||||||
.attach(AdHoc::on_ignite("Database migration", run_migrations_fairing))
|
.attach(AdHoc::on_ignite("Database migration", run_migrations_fairing))
|
||||||
.mount("/api/v1", routes![
|
.mount("/api/v1", routes![
|
||||||
get_zone_records,
|
api::get_zone_records,
|
||||||
create_zone_records,
|
api::create_zone_records,
|
||||||
update_zone_records,
|
api::update_zone_records,
|
||||||
delete_zone_records,
|
api::delete_zone_records,
|
||||||
get_zones,
|
api::get_zones,
|
||||||
create_zone,
|
api::create_zone,
|
||||||
add_member_to_zone,
|
api::add_member_to_zone,
|
||||||
create_auth_token,
|
api::create_auth_token,
|
||||||
create_user,
|
api::create_user,
|
||||||
])
|
])
|
||||||
|
.mount("/", routes![
|
||||||
|
ui::get_login_page,
|
||||||
|
ui::post_login_page,
|
||||||
|
ui::get_zone_records_page,
|
||||||
|
])
|
||||||
|
.mount("/", static_files)
|
||||||
.launch().await;
|
.launch().await;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use serde::{Deserialize, Deserializer};
|
use serde::{Deserialize, Deserializer};
|
||||||
|
|
||||||
|
@ -34,6 +35,8 @@ pub struct TsigConfig {
|
||||||
pub struct WebAppConfig {
|
pub struct WebAppConfig {
|
||||||
#[serde(deserialize_with = "from_std_duration")]
|
#[serde(deserialize_with = "from_std_duration")]
|
||||||
pub token_duration: Duration,
|
pub token_duration: Duration,
|
||||||
|
pub templates_directory: PathBuf,
|
||||||
|
pub static_files: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
42
src/controllers.rs
Normal file
42
src/controllers.rs
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
use time;
|
||||||
|
use rocket::http::{Cookie, SameSite, CookieJar};
|
||||||
|
use rocket::State;
|
||||||
|
|
||||||
|
use crate::config::Config;
|
||||||
|
use crate::DbConn;
|
||||||
|
use crate::models;
|
||||||
|
|
||||||
|
|
||||||
|
pub async fn do_login(
|
||||||
|
conn: DbConn,
|
||||||
|
config: &State<Config>,
|
||||||
|
auth_request: models::AuthTokenRequest,
|
||||||
|
cookies: &CookieJar<'_>
|
||||||
|
) -> Result<models::Session, models::UserError> {
|
||||||
|
let session_duration = config.web_app.token_duration;
|
||||||
|
|
||||||
|
let session = conn.run(move |c| {
|
||||||
|
let user_info = models::LocalUser::get_user_by_creds(
|
||||||
|
c,
|
||||||
|
&auth_request.username,
|
||||||
|
&auth_request.password
|
||||||
|
)?;
|
||||||
|
|
||||||
|
models::Session::new(c, &user_info, session_duration)
|
||||||
|
}).await?;
|
||||||
|
|
||||||
|
// Conversion between different date / time libraries, very cursed, I don't like that
|
||||||
|
// About unwrap: I guess too bad if session time is over year 9999 (current max time if time-rs)
|
||||||
|
let expires = time::OffsetDateTime::from_unix_timestamp(session.expires_at.timestamp()).unwrap();
|
||||||
|
|
||||||
|
let session_cookie = Cookie::build(models::session::COOKIE_NAME, session.session_id.clone())
|
||||||
|
.same_site(SameSite::Strict)
|
||||||
|
.secure(true)
|
||||||
|
.http_only(true)
|
||||||
|
.expires(expires)
|
||||||
|
.finish();
|
||||||
|
|
||||||
|
cookies.add(session_cookie);
|
||||||
|
|
||||||
|
Ok(session)
|
||||||
|
}
|
10
src/main.rs
10
src/main.rs
|
@ -5,12 +5,14 @@
|
||||||
#[macro_use] extern crate diesel;
|
#[macro_use] extern crate diesel;
|
||||||
#[macro_use] extern crate diesel_migrations;
|
#[macro_use] extern crate diesel_migrations;
|
||||||
|
|
||||||
mod models;
|
|
||||||
mod config;
|
|
||||||
mod schema;
|
|
||||||
mod routes;
|
mod routes;
|
||||||
mod dns;
|
|
||||||
mod cli;
|
mod cli;
|
||||||
|
mod config;
|
||||||
|
mod dns;
|
||||||
|
mod models;
|
||||||
|
mod schema;
|
||||||
|
mod template;
|
||||||
|
mod controllers;
|
||||||
|
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ const AUTH_HEADER: &str = "Authorization";
|
||||||
pub const COOKIE_NAME: &str = "session_id";
|
pub const COOKIE_NAME: &str = "session_id";
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize, FromForm)]
|
||||||
pub struct AuthTokenRequest {
|
pub struct AuthTokenRequest {
|
||||||
pub username: String,
|
pub username: String,
|
||||||
pub password: String,
|
pub password: String,
|
||||||
|
|
5
src/routes/api/mod.rs
Normal file
5
src/routes/api/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
pub mod users;
|
||||||
|
pub mod zones;
|
||||||
|
|
||||||
|
pub use users::*;
|
||||||
|
pub use zones::*;
|
|
@ -1,4 +1,4 @@
|
||||||
use rocket::http::{Cookie, SameSite, CookieJar};
|
use rocket::http::CookieJar;
|
||||||
use rocket::serde::json::Json;
|
use rocket::serde::json::Json;
|
||||||
use rocket::State;
|
use rocket::State;
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
|
@ -6,7 +6,8 @@ use rocket::http::Status;
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::DbConn;
|
use crate::DbConn;
|
||||||
use crate::models;
|
use crate::models;
|
||||||
use time;
|
|
||||||
|
use crate::controllers::do_login;
|
||||||
|
|
||||||
|
|
||||||
#[post("/users/me/token", data = "<auth_request>")]
|
#[post("/users/me/token", data = "<auth_request>")]
|
||||||
|
@ -17,32 +18,12 @@ pub async fn create_auth_token(
|
||||||
cookies: &CookieJar<'_>
|
cookies: &CookieJar<'_>
|
||||||
) -> Result<Json<models::Session>, models::ErrorResponse> {
|
) -> Result<Json<models::Session>, models::ErrorResponse> {
|
||||||
|
|
||||||
let session_duration = config.web_app.token_duration;
|
do_login(
|
||||||
|
conn,
|
||||||
let session = conn.run(move |c| {
|
config,
|
||||||
let user_info = models::LocalUser::get_user_by_creds(
|
auth_request.into_inner(),
|
||||||
c,
|
cookies
|
||||||
&auth_request.username,
|
).await.map(|s| Json(s)).map_err(models::ErrorResponse::from)
|
||||||
&auth_request.password
|
|
||||||
)?;
|
|
||||||
|
|
||||||
models::Session::new(c, &user_info, session_duration)
|
|
||||||
}).await?;
|
|
||||||
|
|
||||||
// Conversion between different date / time libraries, very cursed, I don't like that
|
|
||||||
// About unwrap: I guess too bad if session time is over year 9999 (current max time if time-rs)
|
|
||||||
let expires = time::OffsetDateTime::from_unix_timestamp(session.expires_at.timestamp()).unwrap();
|
|
||||||
|
|
||||||
let session_cookie = Cookie::build(models::session::COOKIE_NAME, session.session_id.clone())
|
|
||||||
.same_site(SameSite::Strict)
|
|
||||||
.secure(true)
|
|
||||||
.http_only(true)
|
|
||||||
.expires(expires)
|
|
||||||
.finish();
|
|
||||||
|
|
||||||
cookies.add(session_cookie);
|
|
||||||
|
|
||||||
Ok(Json(session))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/users", data = "<user_request>")]
|
#[post("/users", data = "<user_request>")]
|
|
@ -1,2 +1,2 @@
|
||||||
pub mod users;
|
pub mod ui;
|
||||||
pub mod zones;
|
pub mod api;
|
||||||
|
|
48
src/routes/ui/auth.rs
Normal file
48
src/routes/ui/auth.rs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
use serde::Serialize;
|
||||||
|
use rocket::{State, Either};
|
||||||
|
use rocket::http::{Status, CookieJar};
|
||||||
|
use rocket::form::Form;
|
||||||
|
use rocket::response::Redirect;
|
||||||
|
|
||||||
|
use crate::template::Template;
|
||||||
|
use crate::config::Config;
|
||||||
|
use crate::models;
|
||||||
|
use crate::DbConn;
|
||||||
|
use crate::controllers::do_login;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct LoginPage {
|
||||||
|
error: Option<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[get("/login")]
|
||||||
|
pub async fn get_login_page() -> Template<'static, LoginPage> {
|
||||||
|
Template::new("login.html", LoginPage { error: None })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/login", data = "<auth_request>")]
|
||||||
|
pub async fn post_login_page(
|
||||||
|
conn: DbConn,
|
||||||
|
config: &State<Config>,
|
||||||
|
auth_request: Form<models::AuthTokenRequest>,
|
||||||
|
cookies: &CookieJar<'_>
|
||||||
|
) -> Result<Redirect, Either<Template<'static, LoginPage>, Status>> {
|
||||||
|
let res = do_login(
|
||||||
|
conn,
|
||||||
|
config,
|
||||||
|
auth_request.into_inner(),
|
||||||
|
cookies
|
||||||
|
).await;
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Ok(_) => Ok(Redirect::to(uri!("/zones"))),
|
||||||
|
Err(models::UserError::BadCreds) => Err(Either::Left(Template::new(
|
||||||
|
"login.html",
|
||||||
|
LoginPage {
|
||||||
|
error: Some("Identifants incorrects".to_string())
|
||||||
|
}
|
||||||
|
))),
|
||||||
|
Err(e) => Err(Either::Right(models::ErrorResponse::from(e).status))
|
||||||
|
}
|
||||||
|
}
|
5
src/routes/ui/mod.rs
Normal file
5
src/routes/ui/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
pub mod auth;
|
||||||
|
pub mod zones;
|
||||||
|
|
||||||
|
pub use auth::*;
|
||||||
|
pub use zones::*;
|
30
src/routes/ui/zones.rs
Normal file
30
src/routes/ui/zones.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
use serde::Serialize;
|
||||||
|
use rocket::http::{Status};
|
||||||
|
|
||||||
|
use crate::template::Template;
|
||||||
|
use crate::models;
|
||||||
|
use crate::DbConn;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct RecordsPage {
|
||||||
|
zone: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/zone/<zone>/records")]
|
||||||
|
pub async fn get_zone_records_page(user_info: models::UserInfo, zone: models::AbsoluteName, conn: DbConn) -> Result<Template<'static, RecordsPage>, Status> {
|
||||||
|
let zone_name = zone.to_utf8();
|
||||||
|
|
||||||
|
conn.run(move |c| {
|
||||||
|
if user_info.is_admin() {
|
||||||
|
models::Zone::get_by_name(c, &zone_name)
|
||||||
|
} else {
|
||||||
|
user_info.get_zone(c, &zone_name)
|
||||||
|
}
|
||||||
|
}).await.map_err(|e| models::ErrorResponse::from(e).status)?;
|
||||||
|
|
||||||
|
|
||||||
|
Ok(Template::new("zone/records.html", RecordsPage {
|
||||||
|
zone: zone.to_utf8(),
|
||||||
|
}))
|
||||||
|
}
|
65
src/template.rs
Normal file
65
src/template.rs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
use std::path::Path;
|
||||||
|
use std::process::exit;
|
||||||
|
|
||||||
|
use serde::Serialize;
|
||||||
|
use rocket::request::Request;
|
||||||
|
use rocket::response::{self, Responder};
|
||||||
|
use rocket::http::{Status, ContentType};
|
||||||
|
|
||||||
|
use tera::{Tera, Context};
|
||||||
|
|
||||||
|
|
||||||
|
pub struct TemplateState {
|
||||||
|
tera: Tera,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TemplateState {
|
||||||
|
pub fn new(template_directory: &Path) -> Self {
|
||||||
|
let template_glob = template_directory.join("**").join("*");
|
||||||
|
match Tera::new(template_glob.to_str().expect("valid glob path string")) {
|
||||||
|
Ok(tera) => TemplateState { tera },
|
||||||
|
Err(e) => {
|
||||||
|
println!("Loading templates failed: {}", e);
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Template<'t, S: Serialize> {
|
||||||
|
pub name: &'t str,
|
||||||
|
pub context: S,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'r, S: Serialize> Template<'r, S> {
|
||||||
|
pub fn new(name: &'r str, context: S) -> Self {
|
||||||
|
Template {
|
||||||
|
name,
|
||||||
|
context
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render(self, tera: &Tera) -> Result<(ContentType, String), Status> {
|
||||||
|
let context = Context::from_serialize(self.context).map_err(|e| {
|
||||||
|
error!("Failed to serialize context: {}", e);
|
||||||
|
Status::InternalServerError
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let content = tera.render(self.name, &context).map_err(|e| {
|
||||||
|
error!("Failed to render template `{}`: {}", self.name, e);
|
||||||
|
Status::InternalServerError
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok((ContentType::HTML, content))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'r, 't, S: Serialize> Responder<'r, 'static> for Template<'t, S> {
|
||||||
|
fn respond_to(self, request: &'r Request<'_>) -> response::Result<'static> {
|
||||||
|
let template_state = request.rocket().state::<TemplateState>().ok_or_else(|| {
|
||||||
|
Status::InternalServerError
|
||||||
|
})?;
|
||||||
|
|
||||||
|
self.render(&template_state.tera).respond_to(request)
|
||||||
|
}
|
||||||
|
}
|
13
templates/base.html
Normal file
13
templates/base.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>{% block title %}{% endblock title %}Nomilo</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/styles/main.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% block content %}{% endblock content %}
|
||||||
|
{% block scripts %}{% endblock scripts %}
|
||||||
|
</body>
|
||||||
|
</html>
|
18
templates/login.html
Normal file
18
templates/login.html
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Login ⋅ {% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<main>
|
||||||
|
{% if error %}
|
||||||
|
<p>
|
||||||
|
{{ error }}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
<form method="POST" action="/login">
|
||||||
|
<input type="text" name="username">
|
||||||
|
<input type="password" name="password">
|
||||||
|
<input type="submit" value="Se connecter">
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
{% endblock content %}
|
18
templates/zone/records.html
Normal file
18
templates/zone/records.html
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}{{ zone }} ⋅ Records ⋅ {% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<main></main>
|
||||||
|
{% endblock content %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
<script type="module">
|
||||||
|
const zoneName = "{{ zone }}";
|
||||||
|
|
||||||
|
import { RecordList } from '/scripts/records.js';
|
||||||
|
import { html, render } from 'https://unpkg.com/htm/preact/standalone.mjs';
|
||||||
|
|
||||||
|
render(html`<${RecordList} zone=${zoneName} />`, document.querySelector('main'));
|
||||||
|
</script>
|
||||||
|
{% endblock scripts %}
|
Loading…
Reference in a new issue