Compare commits
3 commits
ebd390987f
...
b9d09e1c99
Author | SHA1 | Date | |
---|---|---|---|
Félix Baylac Jacqué | b9d09e1c99 | ||
Félix Baylac Jacqué | 6ec67b1993 | ||
Félix Baylac Jacqué | 627906e6e6 |
301
Cargo.lock
generated
301
Cargo.lock
generated
|
@ -8,7 +8,7 @@ version = "0.5.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "617a8268e3537fe1d8c9ead925fca49ef6400927ee7bc26750e90ecee14ce4b8"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 1.3.2",
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
|
@ -19,6 +19,29 @@ dependencies = [
|
|||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-files"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf0bdd6ff79de7c9a021f5d9ea79ce23e108d8bfc9b49b5b4a2cf6fad5a35212"
|
||||
dependencies = [
|
||||
"actix-http",
|
||||
"actix-service",
|
||||
"actix-utils",
|
||||
"actix-web",
|
||||
"bitflags 2.4.2",
|
||||
"bytes",
|
||||
"derive_more",
|
||||
"futures-core",
|
||||
"http-range",
|
||||
"log",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"v_htmlescape",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-http"
|
||||
version = "3.3.1"
|
||||
|
@ -31,7 +54,7 @@ dependencies = [
|
|||
"actix-utils",
|
||||
"ahash 0.8.3",
|
||||
"base64 0.21.2",
|
||||
"bitflags",
|
||||
"bitflags 1.3.2",
|
||||
"brotli",
|
||||
"bytes",
|
||||
"bytestring",
|
||||
|
@ -322,6 +345,37 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "aws-config"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "004dc45f6b869e6a70725df448004a720b7f52f6607d55d8815cbd5448f86def"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-http 0.60.0",
|
||||
"aws-runtime",
|
||||
"aws-sdk-sso",
|
||||
"aws-sdk-ssooidc",
|
||||
"aws-sdk-sts",
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-http 0.60.0",
|
||||
"aws-smithy-json 0.60.0",
|
||||
"aws-smithy-runtime",
|
||||
"aws-smithy-runtime-api",
|
||||
"aws-smithy-types",
|
||||
"aws-types",
|
||||
"bytes",
|
||||
"fastrand",
|
||||
"hex",
|
||||
"http",
|
||||
"hyper",
|
||||
"ring",
|
||||
"time",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-credential-types"
|
||||
version = "1.1.0"
|
||||
|
@ -334,6 +388,22 @@ dependencies = [
|
|||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-http"
|
||||
version = "0.60.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "361c4310fdce94328cc2d1ca0c8a48c13f43009c61d3367585685a50ca8c66b6"
|
||||
dependencies = [
|
||||
"aws-smithy-runtime-api",
|
||||
"aws-smithy-types",
|
||||
"aws-types",
|
||||
"bytes",
|
||||
"http",
|
||||
"http-body",
|
||||
"pin-project-lite",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-http"
|
||||
version = "0.61.0"
|
||||
|
@ -357,11 +427,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "5c6d61ac3425f2bd1d69393b96569a7408467f8927a5cfeba597b19f78ebb185"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-http",
|
||||
"aws-http 0.61.0",
|
||||
"aws-sigv4",
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-eventstream",
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-http 0.61.0",
|
||||
"aws-smithy-runtime-api",
|
||||
"aws-smithy-types",
|
||||
"aws-types",
|
||||
|
@ -379,18 +449,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "693ff3ba604fa0db18799fb770c7cde5c3e9302a7b7644647c4e46a615b96e23"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-http",
|
||||
"aws-http 0.61.0",
|
||||
"aws-runtime",
|
||||
"aws-sigv4",
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-checksums",
|
||||
"aws-smithy-eventstream",
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-json",
|
||||
"aws-smithy-http 0.61.0",
|
||||
"aws-smithy-json 0.61.0",
|
||||
"aws-smithy-runtime",
|
||||
"aws-smithy-runtime-api",
|
||||
"aws-smithy-types",
|
||||
"aws-smithy-xml",
|
||||
"aws-smithy-xml 0.61.0",
|
||||
"aws-types",
|
||||
"bytes",
|
||||
"http",
|
||||
|
@ -402,6 +472,73 @@ dependencies = [
|
|||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-sdk-sso"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86575c7604dcdb583aba3390200e5333d8e4fe597bad54f57b190aaf4fac9771"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-http 0.60.0",
|
||||
"aws-runtime",
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-http 0.60.0",
|
||||
"aws-smithy-json 0.60.0",
|
||||
"aws-smithy-runtime",
|
||||
"aws-smithy-runtime-api",
|
||||
"aws-smithy-types",
|
||||
"aws-types",
|
||||
"bytes",
|
||||
"http",
|
||||
"regex",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-sdk-ssooidc"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef0d7c1d0730adb5e85407174483a579e39576e0f4350ecd0fac69ec1217b1b"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-http 0.60.0",
|
||||
"aws-runtime",
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-http 0.60.0",
|
||||
"aws-smithy-json 0.60.0",
|
||||
"aws-smithy-runtime",
|
||||
"aws-smithy-runtime-api",
|
||||
"aws-smithy-types",
|
||||
"aws-types",
|
||||
"bytes",
|
||||
"http",
|
||||
"regex",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-sdk-sts"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f45778089751d5aa8645a02dd60865fa0eea39f00be5db2c7779bc50b83db19a"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-http 0.60.0",
|
||||
"aws-runtime",
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-http 0.60.0",
|
||||
"aws-smithy-json 0.60.0",
|
||||
"aws-smithy-query",
|
||||
"aws-smithy-runtime",
|
||||
"aws-smithy-runtime-api",
|
||||
"aws-smithy-types",
|
||||
"aws-smithy-xml 0.60.3",
|
||||
"aws-types",
|
||||
"http",
|
||||
"regex",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-sigv4"
|
||||
version = "1.1.0"
|
||||
|
@ -410,7 +547,7 @@ checksum = "82f39bf5bfa061fd1487a7ba274927dd6d70feed5cecaf3367932bcc83148d8f"
|
|||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-smithy-eventstream",
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-http 0.61.0",
|
||||
"aws-smithy-runtime-api",
|
||||
"aws-smithy-types",
|
||||
"bytes",
|
||||
|
@ -447,7 +584,7 @@ version = "0.61.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3c4fd37c10269ad70de25cfbe29f52c1ae6fc48606a2b1ed2c4bdeb624d5da9"
|
||||
dependencies = [
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-http 0.61.0",
|
||||
"aws-smithy-types",
|
||||
"bytes",
|
||||
"crc32c",
|
||||
|
@ -473,6 +610,26 @@ dependencies = [
|
|||
"crc32fast",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-http"
|
||||
version = "0.60.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b1de8aee22f67de467b2e3d0dd0fb30859dc53f579a63bd5381766b987db644"
|
||||
dependencies = [
|
||||
"aws-smithy-runtime-api",
|
||||
"aws-smithy-types",
|
||||
"bytes",
|
||||
"bytes-utils",
|
||||
"futures-core",
|
||||
"http",
|
||||
"http-body",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-http"
|
||||
version = "0.61.0"
|
||||
|
@ -494,6 +651,15 @@ dependencies = [
|
|||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-json"
|
||||
version = "0.60.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a46dd338dc9576d6a6a5b5a19bd678dcad018ececee11cf28ecd7588bd1a55c"
|
||||
dependencies = [
|
||||
"aws-smithy-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-json"
|
||||
version = "0.61.0"
|
||||
|
@ -503,6 +669,16 @@ dependencies = [
|
|||
"aws-smithy-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-query"
|
||||
version = "0.60.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "feb5b8c7a86d4b6399169670723b7e6f21a39fc833a30f5c5a2f997608178129"
|
||||
dependencies = [
|
||||
"aws-smithy-types",
|
||||
"urlencoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-runtime"
|
||||
version = "1.1.0"
|
||||
|
@ -510,7 +686,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "0de8c54dd9c5a159013f1e6885cb7c1ae8fc98dc286d2aebe71737effef28e37"
|
||||
dependencies = [
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-http 0.61.0",
|
||||
"aws-smithy-runtime-api",
|
||||
"aws-smithy-types",
|
||||
"bytes",
|
||||
|
@ -541,6 +717,7 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -566,6 +743,15 @@ dependencies = [
|
|||
"tokio-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-xml"
|
||||
version = "0.60.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef796feaf894d7fd03869235237aeffe73ed1b29a3927cceeee2eecadf876eba"
|
||||
dependencies = [
|
||||
"xmlparser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-xml"
|
||||
version = "0.61.0"
|
||||
|
@ -656,6 +842,12 @@ version = "1.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.3"
|
||||
|
@ -760,7 +952,7 @@ version = "4.0.29"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 1.3.2",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"is-terminal",
|
||||
|
@ -1398,6 +1590,12 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-range"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573"
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.8.0"
|
||||
|
@ -1631,6 +1829,16 @@ version = "0.3.16"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
||||
|
||||
[[package]]
|
||||
name = "mime_guess"
|
||||
version = "2.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
|
||||
dependencies = [
|
||||
"mime",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
|
@ -1672,16 +1880,22 @@ dependencies = [
|
|||
name = "nom-nom-gc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"actix-files",
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
"aws-config",
|
||||
"aws-sdk-s3",
|
||||
"aws-types",
|
||||
"chrono",
|
||||
"clap",
|
||||
"deadpool-postgres",
|
||||
"handlebars",
|
||||
"heck",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"postgres-types",
|
||||
"refinery",
|
||||
"rust-embed",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
|
@ -1761,7 +1975,7 @@ version = "0.10.45"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
|
@ -2078,7 +2292,7 @@ version = "0.2.16"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2186,6 +2400,40 @@ dependencies = [
|
|||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed"
|
||||
version = "8.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a82c0bbc10308ed323529fd3c1dce8badda635aa319a5ff0e6466f33b8101e3f"
|
||||
dependencies = [
|
||||
"rust-embed-impl",
|
||||
"rust-embed-utils",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed-impl"
|
||||
version = "8.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6227c01b1783cdfee1bcf844eb44594cd16ec71c35305bf1c9fb5aade2735e16"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rust-embed-utils",
|
||||
"syn 2.0.37",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed-utils"
|
||||
version = "8.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cb0a25bfbb2d4b4402179c2cf030387d9990857ce08a32592c6238db9fa8665"
|
||||
dependencies = [
|
||||
"sha2",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
|
@ -2216,7 +2464,7 @@ version = "0.36.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 1.3.2",
|
||||
"errno",
|
||||
"io-lifetimes",
|
||||
"libc",
|
||||
|
@ -2333,7 +2581,7 @@ version = "2.9.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
|
@ -2822,6 +3070,15 @@ version = "0.1.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
|
||||
dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.8"
|
||||
|
@ -2873,6 +3130,12 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urlencoding"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.4.1"
|
||||
|
@ -2883,6 +3146,12 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "v_htmlescape"
|
||||
version = "0.15.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
|
|
|
@ -7,6 +7,10 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
actix-web = "4"
|
||||
actix-files = "*"
|
||||
mime = "*"
|
||||
mime_guess = "*"
|
||||
rust-embed = "*"
|
||||
clap = { version = "4.0.29", features = ["derive"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
url = "*"
|
||||
|
@ -22,6 +26,8 @@ refinery = { version = "0.8.11", features = ["tokio-postgres"] }
|
|||
uuid = { version = "1.4.1", features = ["v4"] }
|
||||
chrono = { version = "*", features = ["serde"] }
|
||||
aws-sdk-s3 = "1.6.0"
|
||||
aws-config = "1.0.3"
|
||||
aws-types = "*"
|
||||
|
||||
[dependencies.heck]
|
||||
version = "0.4.1"
|
||||
|
|
|
@ -30,6 +30,7 @@ CREATE TABLE Projects (
|
|||
id SERIAL PRIMARY KEY NOT NULL,
|
||||
name text NOT NULL UNIQUE,
|
||||
binary_cache_id integer NOT NULL,
|
||||
closure_generation_nb integer NOT NULL,
|
||||
-- TODO: figure out rules
|
||||
CONSTRAINT fk_project_binary_cache FOREIGN KEY (binary_cache_id) REFERENCES BinaryCaches(id)
|
||||
);
|
||||
|
@ -43,13 +44,28 @@ CREATE TABLE ProjectTokens (
|
|||
|
||||
CREATE TABLE Closures (
|
||||
id SERIAL PRIMARY KEY NOT NULL,
|
||||
project_id integer NOT NULL,
|
||||
project_id INTEGER NOT NULL,
|
||||
objects text[] NOT NULL,
|
||||
date timestamp NOT NULL,
|
||||
CONSTRAINT fk_project_closure FOREIGN KEY (project_id) REFERENCES Projects(id)
|
||||
);
|
||||
|
||||
CREATE TABLE Objects (
|
||||
id SERIAL PRIMARY KEY NOT NULL,
|
||||
key text NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE ObjectClosure (
|
||||
object_id INTEGER NOT NULL,
|
||||
closure_id INTEGER NOT NULL,
|
||||
CONSTRAINT fk_objectclosure_object FOREIGN KEY (object_id) REFERENCES Objects(id),
|
||||
CONSTRAINT fk_objectclosure_closure FOREIGN KEY (closure_id) REFERENCES Closures(id),
|
||||
PRIMARY KEY (object_id, closure_id)
|
||||
);
|
||||
|
||||
-- We'll mostly querying the Keys using the associated uid.
|
||||
CREATE INDEX idx_keys_uid ON Keys USING HASH (user_id);
|
||||
-- We'll be often sorting Closures through their datetime.
|
||||
CREATE INDEX idx_date_closures ON Closures USING HASH (date);
|
||||
-- We'll be querying objects through their names.
|
||||
CREATE INDEX idx_objects_key ON Objects USING HASH (key);
|
||||
|
|
|
@ -6,11 +6,14 @@ dbname="nomnomdev"
|
|||
port="12345"
|
||||
|
||||
dbdir="$(mktemp -d)"
|
||||
garagedir="$(mktemp -d)"
|
||||
garageaddr="[::1]:3900"
|
||||
garagebucket="nix-cache"
|
||||
cfgfile="${dbdir}/config.json"
|
||||
trap 'rm -rf ${dbdir}' EXIT
|
||||
|
||||
initdb "$dbdir"
|
||||
postgres -D "${dbdir}" -c unix_socket_directories="${dbdir}" -c listen_addresses= -c port="${port}" &
|
||||
postgres -D "${dbdir}" -c unix_socket_directories="${dbdir}" -c listen_addresses= -c port="${port}" > /dev/null &
|
||||
pgpid=$!
|
||||
|
||||
# Trick to help the "./psql" script to find the DB dir & co
|
||||
|
@ -21,19 +24,79 @@ export dbname="$dbname"
|
|||
export cfgfile="$cfgfile"
|
||||
EOF
|
||||
|
||||
trap 'rm -rf ${dbdir} && rm /tmp/nom-nom-dev-args && kill ${pgpid}' EXIT
|
||||
# Garage Directory
|
||||
cat <<EOF > "$garagedir/config.toml"
|
||||
metadata_dir = "$garagedir/meta"
|
||||
data_dir = "$garagedir/data"
|
||||
|
||||
block_size = 1048576
|
||||
|
||||
replication_mode = "1"
|
||||
|
||||
compression_level = 1
|
||||
|
||||
rpc_secret = "4425f5c26c5e11581d3223904324dcb5b5d5dfb14e5e7f35e38c595424f5f1e6"
|
||||
rpc_bind_addr = "[::]:3901"
|
||||
rpc_public_addr = "[::]:3901"
|
||||
|
||||
bootstrap_peers = [
|
||||
]
|
||||
|
||||
consul_host = "consul.service"
|
||||
consul_service_name = "garage-daemon"
|
||||
|
||||
sled_cache_capacity = 134217728
|
||||
sled_flush_every_ms = 2000
|
||||
|
||||
[s3_api]
|
||||
api_bind_addr = "${garageaddr}"
|
||||
s3_region = "garage"
|
||||
root_domain = ".s3.garage"
|
||||
|
||||
[s3_web]
|
||||
bind_addr = "[::]:3902"
|
||||
root_domain = ".web.garage"
|
||||
index = "index.html"
|
||||
EOF
|
||||
|
||||
garage -c "$garagedir/config.toml" server &
|
||||
garagepid=$!
|
||||
|
||||
trap 'rm -rf ${dbdir} && rm -rf ${garagedir} && rm /tmp/nom-nom-dev-args && kill ${pgpid} && kill ${garagepid}' EXIT
|
||||
|
||||
# Yeah, this is very meh. We need to wait for the server to be ready
|
||||
# to receive requests to create the DB.
|
||||
sleep 2
|
||||
createdb -h "${dbdir}" -p "${port}" "${dbname}"
|
||||
|
||||
garage -c "$garagedir/config.toml" status
|
||||
garagenodeid=$(garage -c "$garagedir/config.toml" node id | cut -f 1 -d '@')
|
||||
garage -c "$garagedir/config.toml" layout assign "$garagenodeid" -c 500MB -z zone
|
||||
garage -c "$garagedir/config.toml" layout show
|
||||
garage -c "$garagedir/config.toml" layout apply --version 1
|
||||
garage -c "$garagedir/config.toml" status
|
||||
garage -c "$garagedir/config.toml" bucket create "${garagebucket}"
|
||||
garage -c "$garagedir/config.toml" key create nomnom-key
|
||||
garage -c "$garagedir/config.toml" bucket allow --read --write --owner "${garagebucket}" --key nomnom-key
|
||||
garagekeyid=$(garage -c "$garagedir/config.toml" key info nomnom-key | grep "Key ID" | cut -f3 -d " ")
|
||||
garagekeysecret=$(garage -c "$garagedir/config.toml" key info --show-secret nomnom-key | grep "Secret key" | cut -f3 -d " ")
|
||||
|
||||
access_key_filepath=$(mktemp)
|
||||
echo "${garagekeyid}" > "${access_key_filepath}"
|
||||
secret_key_filepath=$(mktemp)
|
||||
echo "${garagekeysecret}" > "${secret_key_filepath}"
|
||||
|
||||
cat <<EOF > "${cfgfile}"
|
||||
{
|
||||
"url": "http://localhost:8001",
|
||||
"db_host": "${dbdir}",
|
||||
"db_port": ${port},
|
||||
"db_name": "${dbname}"
|
||||
"db_name": "${dbname}",
|
||||
"s3_endpoint": "http://${garageaddr}",
|
||||
"s3_region": "garage",
|
||||
"s3_bucket": "${garagebucket}",
|
||||
"s3_access_key_filepath": "${access_key_filepath}",
|
||||
"s3_secret_key_filepath": "${secret_key_filepath}"
|
||||
}
|
||||
EOF
|
||||
|
||||
|
@ -45,4 +108,4 @@ if [ -f dump.sql ]; then
|
|||
./psql -f dump.sql
|
||||
fi
|
||||
|
||||
cargo run --bin nom-nom-gc-server -- --bind "[::1]:8001" --config "${cfgfile}"
|
||||
RUST_BACKTRACE=1 cargo run --bin nom-nom-gc-server -- --bind "[::1]:8001" --config "${cfgfile}"
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
pkgs.mkShell {
|
||||
nativeBuildInputs = [
|
||||
pkgs.rustc
|
||||
pkgs.rustfmt
|
||||
pkgs.cargo
|
||||
pkgs.rust-analyzer
|
||||
pkgs.pkg-config
|
||||
pkgs.postgresql
|
||||
pkgs.garage
|
||||
];
|
||||
buildInputs = [
|
||||
pkgs.openssl
|
||||
|
|
|
@ -29,7 +29,7 @@ async fn main() -> Result<()> {
|
|||
let config = read_config(&args.config.unwrap_or("/etc/nom-nom-gc/config.json".to_owned()))
|
||||
.unwrap_or_else(|e| panic!("Cannot read config file: {}", e));
|
||||
// todo: don't consume config in appstate new
|
||||
let state = models::AppState::new(config.clone());
|
||||
let state = models::AppState::new(config.clone()).await;
|
||||
match args.command {
|
||||
Command::RegisterUser(args) => register_user(args.username, state, config).await,
|
||||
}
|
||||
|
|
|
@ -31,3 +31,7 @@ pub async fn new_binary_cache_post(app_state: web::Data<AppState<'_>>, req: Http
|
|||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_binary_cache(_app_state: web::Data<AppState<'_>>, _req: HttpRequest, _path: web::Path<String>) -> impl Responder {
|
||||
HttpResponse::NotImplemented().finish()
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use actix_web::{HttpResponse, http::header::{ContentType, self}, web, HttpRequest, cookie::{Cookie, SameSite}};
|
||||
use chrono::Local;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{models::{AppState, SessionUuid, User, ProjectSummary}, templates};
|
||||
use crate::{models::{AppState, SessionUuid, User}, templates};
|
||||
|
||||
pub mod authentication;
|
||||
pub mod binary_cache;
|
||||
|
@ -11,14 +10,14 @@ pub use authentication::*;
|
|||
pub use binary_cache::*;
|
||||
|
||||
pub async fn landing_page (app_state: web::Data<AppState<'_>>) -> HttpResponse {
|
||||
let summaries: Vec<ProjectSummary> = vec![
|
||||
/* let summaries: Vec<ProjectSummary> = vec![
|
||||
ProjectSummary {
|
||||
name: "Test Project".to_string(),
|
||||
latest_closure: "/nix/store/blabla".to_string(),
|
||||
latest_closure_datetime: Local::now(),
|
||||
}
|
||||
];
|
||||
let content: String = templates::landing_page(app_state.hbs.clone(), true, summaries).unwrap();
|
||||
];*/
|
||||
let content: String = templates::landing_page(app_state.hbs.clone(), true).unwrap();
|
||||
HttpResponse::Ok()
|
||||
.content_type(ContentType::html())
|
||||
.body(content)
|
||||
|
@ -64,7 +63,7 @@ async fn check_authentication(app_state: &web::Data<AppState<'_>>, req: HttpRequ
|
|||
let auth_session = app_state.session.user_sessions.read().await;
|
||||
let cookie = req.cookie("auth-uuid").ok_or_else(|| redirect_to_login("missing cookie in request", &req))?;
|
||||
let cookie = cookie.value();
|
||||
let client_uuid = Uuid::parse_str(&cookie).map_err(|e| redirect_to_login(e, &req))?;
|
||||
let client_uuid = Uuid::parse_str(cookie).map_err(|e| redirect_to_login(e, &req))?;
|
||||
let user = auth_session.get(&SessionUuid(client_uuid)).ok_or_else(|| redirect_to_login("cannot find UUID in session", &req))?;
|
||||
Ok(user.clone())
|
||||
}
|
||||
|
|
|
@ -2,3 +2,4 @@ pub mod app;
|
|||
pub mod handlers;
|
||||
pub mod models;
|
||||
pub mod templates;
|
||||
pub mod s3;
|
||||
|
|
|
@ -2,7 +2,10 @@ use std::collections::HashMap;
|
|||
use std::fs;
|
||||
use std::ops::DerefMut;
|
||||
use std::sync::Arc;
|
||||
use chrono::{DateTime, Local};
|
||||
use aws_config::{BehaviorVersion, Region};
|
||||
|
||||
use aws_sdk_s3::config::{Credentials, SharedCredentialsProvider};
|
||||
|
||||
use postgres_types::{FromSql, ToSql};
|
||||
use url::Url;
|
||||
|
||||
|
@ -23,7 +26,12 @@ pub struct Configuration {
|
|||
pub url: String,
|
||||
pub db_host: Option<String>,
|
||||
pub db_port: Option<u16>,
|
||||
pub db_name: String
|
||||
pub db_name: String,
|
||||
pub s3_endpoint: String,
|
||||
pub s3_region: String,
|
||||
pub s3_bucket: String,
|
||||
pub s3_access_key_filepath: String,
|
||||
pub s3_secret_key_filepath: String
|
||||
}
|
||||
|
||||
|
||||
|
@ -71,7 +79,8 @@ pub struct AppState<'a>{
|
|||
pub webauthn: Arc<Webauthn>,
|
||||
pub db: Pool,
|
||||
pub hbs: Arc<Handlebars<'a>>,
|
||||
pub session: TempSession
|
||||
pub session: TempSession,
|
||||
pub s3_client: aws_sdk_s3::Client
|
||||
}
|
||||
|
||||
mod embedded {
|
||||
|
@ -91,23 +100,17 @@ pub struct BinaryCache {
|
|||
pub access_key: String,
|
||||
pub secret_key: String,
|
||||
pub region: String,
|
||||
pub endpoint: String
|
||||
pub endpoint_url: String
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Project {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ProjectSummary {
|
||||
pub name: String,
|
||||
pub latest_closure: String,
|
||||
pub latest_closure_datetime: DateTime<Local>
|
||||
pub latest_closure_generation: u32
|
||||
}
|
||||
|
||||
impl AppState<'_> {
|
||||
pub fn new(conf: Configuration) -> Self {
|
||||
pub async fn new(conf: Configuration) -> Self {
|
||||
let rp = "localhost";
|
||||
let rp_origin = Url::parse(&conf.url).expect("Invalid URL");
|
||||
let builder = WebauthnBuilder::new(rp, &rp_origin).expect("Invalid configuration");
|
||||
|
@ -128,12 +131,26 @@ impl AppState<'_> {
|
|||
};
|
||||
let mgr = Manager::from_config(pg_config, NoTls, mgr_config);
|
||||
let pool = Pool::builder(mgr).max_size(16).build().unwrap();
|
||||
|
||||
let access_key = fs::read_to_string(&conf.s3_access_key_filepath)
|
||||
.unwrap_or_else(|_| format!("Cannot read the S3 access key from {}", &conf.s3_access_key_filepath.clone()));
|
||||
let secret_key = fs::read_to_string(&conf.s3_secret_key_filepath)
|
||||
.unwrap_or_else(|_| format!("Cannot read the S3 secret key from {}", &conf.s3_secret_key_filepath.clone()));
|
||||
let access_key = access_key.strip_suffix('\n').unwrap_or(&access_key);
|
||||
let secret_key = secret_key.strip_suffix('\n').unwrap_or(&secret_key);
|
||||
let credentials = Credentials::new(access_key, secret_key, None, None, "nom-nom-provider");
|
||||
let s3_client_config = aws_config::SdkConfig::builder()
|
||||
.endpoint_url(conf.s3_endpoint)
|
||||
.region(Some(Region::new(conf.s3_region)))
|
||||
.credentials_provider(SharedCredentialsProvider::new(credentials))
|
||||
.behavior_version(BehaviorVersion::latest())
|
||||
.build();
|
||||
let s3_client = aws_sdk_s3::Client::new(&s3_client_config);
|
||||
AppState {
|
||||
webauthn,
|
||||
db: pool,
|
||||
hbs,
|
||||
session
|
||||
session,
|
||||
s3_client
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,13 +215,13 @@ impl AppState<'_> {
|
|||
pub async fn create_binary_cache(&self, binary_cache: &BinaryCache) -> Result<()> {
|
||||
let conn = self.db.get().await?;
|
||||
let stmt = conn.prepare_cached("INSERT INTO BinaryCaches (name, access_key, secret_key, region, endpoint) VALUES ($1, $2, $3, $4, $5)").await?;
|
||||
let _ = conn.execute(&stmt, &[&binary_cache.name, &binary_cache.access_key, &binary_cache.secret_key, &binary_cache.region, &binary_cache.endpoint]).await?;
|
||||
let _ = conn.execute(&stmt, &[&binary_cache.name, &binary_cache.access_key, &binary_cache.secret_key, &binary_cache.region, &binary_cache.endpoint_url]).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn create_project(&self, binary_cache: &BinaryCache, project: &Project) -> Result<()> {
|
||||
let conn = self.db.get().await?;
|
||||
let stmt = conn.prepare_cached("INSERT INTO Projects (name, binary_cache_id) \
|
||||
let stmt = conn.prepare_cached("INSERT INTO Projects (name, binary_cache_id, 0) \
|
||||
SELECT $1, b.id FROM BinaryCaches b \
|
||||
WHERE b.name = $2").await?;
|
||||
let _ = conn.execute(&stmt, &[&project.name, &binary_cache.name]).await?;
|
||||
|
@ -223,16 +240,17 @@ impl AppState<'_> {
|
|||
|
||||
pub async fn get_project(&self, token: &ProjectUuid) -> Result<Project> {
|
||||
let conn = self.db.get().await?;
|
||||
let stmt = conn.prepare_cached("SELECT name FROM Projects p \
|
||||
let stmt = conn.prepare_cached("SELECT name, closure_generation FROM Projects p \
|
||||
INNER JOIN ProjectTokens t ON p.id = t.project_id \
|
||||
WHERE t.token = $1").await?;
|
||||
let row = conn.query_one(&stmt, &[&token.0]).await?;
|
||||
Ok(Project {
|
||||
name: row.get(0)
|
||||
name: row.get(0),
|
||||
latest_closure_generation: row.get(1)
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn get_project_summaries(&self) -> Result<Vec<ProjectSummary>> {
|
||||
/* pub async fn get_project_summaries(&self) -> Result<Vec<ProjectSummary>> {
|
||||
let conn = self.db.get().await?;
|
||||
let stmt = conn.prepare_cached("SELECT p.name, p FROM Projects p \
|
||||
INNER JOIN Closures c ON c.project_id = p.id").await?;
|
||||
|
@ -244,5 +262,5 @@ impl AppState<'_> {
|
|||
latest_closure_datetime: r.get(2)
|
||||
}).collect()
|
||||
)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
10
src/s3/mod.rs
Normal file
10
src/s3/mod.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use aws_sdk_s3::{operation::head_bucket::HeadBucketOutput, Client};
|
||||
|
||||
use crate::models::Configuration;
|
||||
|
||||
pub async fn check_bucket(client: &Client, config: &Configuration) -> Result<HeadBucketOutput> {
|
||||
println!("{}",&config.s3_bucket);
|
||||
let res = client.head_bucket().bucket(&config.s3_bucket).send().await;
|
||||
res.map_err(|e| anyhow!("Cannot access the binary cache bucket: {}", e))
|
||||
}
|
|
@ -1,11 +1,14 @@
|
|||
use std::net::SocketAddr;
|
||||
|
||||
use actix_web::{App, web, HttpServer};
|
||||
use actix_web::{App, web, HttpServer, HttpResponse};
|
||||
use clap::Parser;
|
||||
|
||||
use mime_guess::from_path;
|
||||
use nom_nom_gc::handlers;
|
||||
use nom_nom_gc::models::read_config;
|
||||
use nom_nom_gc::models;
|
||||
use nom_nom_gc::s3::check_bucket;
|
||||
use rust_embed::RustEmbed;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
|
@ -16,6 +19,19 @@ struct CLIArgs {
|
|||
config: Option<String>
|
||||
}
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "src/static"]
|
||||
struct Static;
|
||||
|
||||
async fn handle_embedded_file(path: web::Path<String>) -> HttpResponse {
|
||||
match Static::get(&path) {
|
||||
Some(content) => HttpResponse::Ok()
|
||||
.content_type(from_path(&*path).first_or_octet_stream().as_ref())
|
||||
.body(content.data.into_owned()),
|
||||
None => HttpResponse::NotFound().body("404 Not Found"),
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
let args = CLIArgs::parse();
|
||||
|
@ -23,14 +39,20 @@ async fn main() -> std::io::Result<()> {
|
|||
let config_path = args.config.unwrap_or("/etc/nom-nom-gc/config.json".to_owned());
|
||||
let config = read_config(&config_path)
|
||||
.unwrap_or_else(|e| panic!("Cannot read config file: {}", e));
|
||||
let state = models::AppState::new(config);
|
||||
let state = models::AppState::new(config.clone()).await;
|
||||
println!("Running DB migrations");
|
||||
state.run_migrations().await.unwrap_or_else(|e| panic!("Db migration error: {}", e));
|
||||
|
||||
println!("Checking binary cache bucket");
|
||||
let bucket = check_bucket(&state.s3_client, &config).await;
|
||||
match bucket {
|
||||
Ok(_) => println!("Connection to the bucket successful"),
|
||||
Err(e) => panic!("Cannot connect to the binary cache bucket: {}", e)
|
||||
}
|
||||
println!("Server listening to {}", &args.bind);
|
||||
HttpServer::new(
|
||||
move || {
|
||||
App::new().app_data(web::Data::new(state.clone()))
|
||||
App::new()
|
||||
.app_data(web::Data::new(state.clone()))
|
||||
.route("/", web::get().to(handlers::landing_page))
|
||||
.route("/account/register/{uuid}", web::get().to(handlers::webauthn_registration))
|
||||
.route("/account/register-init", web::post().to(handlers::start_webauthn_registration))
|
||||
|
@ -40,6 +62,8 @@ async fn main() -> std::io::Result<()> {
|
|||
.route("/login/finish", web::post().to(handlers::webauthn_login_finish))
|
||||
.route("/binary-cache/new", web::get().to(handlers::new_binary_cache))
|
||||
.route("/binary-cache/new", web::post().to(handlers::new_binary_cache_post))
|
||||
.route("/binary-cache/{id}", web::get().to(handlers::get_binary_cache))
|
||||
.route("/static/{_:.*}", web::get().to(handle_embedded_file))
|
||||
})
|
||||
.bind(addr)
|
||||
.unwrap()
|
||||
|
|
BIN
src/static/malix.webp
Normal file
BIN
src/static/malix.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
|
@ -3,21 +3,7 @@
|
|||
<a href="/binary-cache/new">New Binary Cache</a>
|
||||
{{#each binaryCaches}}
|
||||
<div class="binary-cache">
|
||||
<h3>{{this.name}}</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Project Name</th>
|
||||
<th>Latest Closure</th>
|
||||
<th>Datetime</th>
|
||||
</tr>
|
||||
{{#each this.projects}}
|
||||
<tr>
|
||||
<td>{{this.name}}</td>
|
||||
<td>{{this.latestClosure}}</td>
|
||||
<td>{{this.datetime}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
<h3><a href="/binary-cache/{{this.id}}">{{this.name}}</a></h3>
|
||||
</div>
|
||||
{{/each}}
|
||||
{{ /template }}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{{#> template js=js }}
|
||||
<h1>Login</h1>
|
||||
<form id="key-form"><label>Username</label><input id="user-name"/><input type="submit" value="Login" id="login-btn"/></form>
|
||||
<form id="key-form"><label>Username</label><input id="user-name"/><input type="submit" value="Login" id="submit"/></form>
|
||||
{{ /template }}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
body {
|
||||
background-color: #F9FA57;
|
||||
background-color: #FFEE00;
|
||||
color: black;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
@ -19,17 +19,22 @@ main {
|
|||
}
|
||||
|
||||
nav {
|
||||
padding: 1em;
|
||||
padding: .5em;
|
||||
margin: 1em;
|
||||
background-color: white;
|
||||
box-shadow: 10px 15px #C800E4;
|
||||
border: 2px solid black;
|
||||
}
|
||||
|
||||
nav > ul {
|
||||
margin: 0;
|
||||
padding-left: 0;
|
||||
font-size: 2em;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
list-style-type: none;
|
||||
align-items: center;
|
||||
flex-basis: 90%;
|
||||
}
|
||||
|
||||
#main-container {
|
||||
|
@ -38,4 +43,50 @@ nav > ul {
|
|||
width: 85%;
|
||||
padding: 2em;
|
||||
margin: 1em;
|
||||
border: 2px solid black;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 20em;
|
||||
margin: auto;
|
||||
padding: 1em;
|
||||
border: 3px solid;
|
||||
border-radius: 9px;
|
||||
}
|
||||
|
||||
form > label {
|
||||
margin-top: .5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
form > input {
|
||||
border: 2px solid black;
|
||||
border-radius: 10px;
|
||||
padding-left: 1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
form > #submit {
|
||||
margin-top: 3em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#logo-txt {
|
||||
font-size: .4em;
|
||||
color: #C800E4;
|
||||
}
|
||||
|
||||
#nom-nom-gc-txt {
|
||||
writing-mode: vertical-rl;
|
||||
color: #C800E4;
|
||||
font-weight: bold;
|
||||
font-size: 2em;
|
||||
margin-left: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
}
|
||||
|
|
|
@ -1,46 +1,44 @@
|
|||
use handlebars::RenderError;
|
||||
use rust_embed::RustEmbed;
|
||||
use serde_json::json;
|
||||
use handlebars::Handlebars;
|
||||
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
use std::{sync::Arc, str::from_utf8};
|
||||
|
||||
use crate::models::{RegistrationUuid, ProjectSummary};
|
||||
use crate::models::RegistrationUuid;
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "src/templates"]
|
||||
struct Templates;
|
||||
|
||||
pub fn new<'a>() -> Result<Handlebars<'a>, RenderError> {
|
||||
let rootpath = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
let landing_path = rootpath.join("src/templates/landing.hbs");
|
||||
let template_path = rootpath.join("src/templates/template.hbs");
|
||||
let register_user = rootpath.join("src/templates/register-user.hbs");
|
||||
let landing_path = Templates::get("landing.hbs").unwrap();
|
||||
let template_path = Templates::get("template.hbs").unwrap();
|
||||
let register_user = Templates::get("register-user.hbs").unwrap();
|
||||
let mut hbs = handlebars::Handlebars::new();
|
||||
let css = rootpath.join("src/templates/main.css");
|
||||
let webauthn_register_js = rootpath.join("src/templates/webauthn-register.js");
|
||||
let webauthn_login_js = rootpath.join("src/templates/webauthn-login.js");
|
||||
let login = rootpath.join("src/templates/login.hbs");
|
||||
let new_binary_cache_form = rootpath.join("src/templates/new-binary-cache.hbs");
|
||||
let css = Templates::get("main.css").unwrap();
|
||||
let webauthn_register_js =Templates::get("webauthn-register.js").unwrap();
|
||||
let webauthn_login_js = Templates::get("webauthn-login.js").unwrap();
|
||||
let login = Templates::get("login.hbs").unwrap();
|
||||
let new_binary_cache_form = Templates::get("new-binary-cache.hbs").unwrap();
|
||||
|
||||
hbs.register_template_file("landing", landing_path.to_str().unwrap())?;
|
||||
hbs.register_template_file("template", template_path.to_str().unwrap())?;
|
||||
hbs.register_template_file("css", css.to_str().unwrap())?;
|
||||
hbs.register_template_file("webauthn-register-js", webauthn_register_js.to_str().unwrap())?;
|
||||
hbs.register_template_file("webauthn-login-js", webauthn_login_js.to_str().unwrap())?;
|
||||
hbs.register_template_file("register-user", register_user.to_str().unwrap())?;
|
||||
hbs.register_template_file("login", login.to_str().unwrap())?;
|
||||
hbs.register_template_file("new-binary-cache-form", new_binary_cache_form.to_str().unwrap())?;
|
||||
hbs.register_template_string("landing", from_utf8(&landing_path.data).unwrap())?;
|
||||
hbs.register_template_string("template", from_utf8(&template_path.data).unwrap())?;
|
||||
hbs.register_template_string("css", from_utf8(&css.data).unwrap())?;
|
||||
hbs.register_template_string("webauthn-register-js", from_utf8(&webauthn_register_js.data).unwrap())?;
|
||||
hbs.register_template_string("webauthn-login-js", from_utf8(&webauthn_login_js.data).unwrap())?;
|
||||
hbs.register_template_string("register-user", from_utf8(®ister_user.data).unwrap())?;
|
||||
hbs.register_template_string("login", from_utf8(&login.data).unwrap())?;
|
||||
hbs.register_template_string("new-binary-cache-form", from_utf8(&new_binary_cache_form.data).unwrap())?;
|
||||
|
||||
Ok(hbs)
|
||||
}
|
||||
|
||||
pub fn landing_page(hb: Arc<Handlebars<'_>>, logged: bool, project_summaries: Vec<ProjectSummary>) -> Result<String, RenderError> {
|
||||
pub fn landing_page(hb: Arc<Handlebars<'_>>, _logged: bool) -> Result<String, RenderError> {
|
||||
let data = json!({
|
||||
"binaryCaches": [{
|
||||
"name": "NixOS Binary Cache",
|
||||
"projects": project_summaries.into_iter().map(|p| json!({
|
||||
"name": p.name,
|
||||
"latestClosure": p.latest_closure,
|
||||
"datetime": p.latest_closure_datetime.to_string()
|
||||
}
|
||||
)).collect::<Vec<_>>()
|
||||
}]});
|
||||
}]
|
||||
});
|
||||
hb.render("landing", &data)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
{{#> template }}
|
||||
<h1>New Binary Cache</h1>
|
||||
<form name="binary-cache" method="post" action="/binary-cache/new">
|
||||
<form id="binary-cache-form" name="binary-cache" method="post" action="/binary-cache/new">
|
||||
<label>Bucket Name</label>
|
||||
<input name="name"/>
|
||||
<input name="name" placeholder="Nix Cache"/>
|
||||
<label>Bucket Access Key</label>
|
||||
<input name="access_key"/>
|
||||
<input name="access_key" placeholder="AKIAIOSFODNN7EXAMPLE"/>
|
||||
<label>Bucket Secret Key</label>
|
||||
<input name="secret_key"/>
|
||||
<input name="secret_key" placeholder="JalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"/>
|
||||
<label>Bucket Region</label>
|
||||
<input name="region"/>
|
||||
<input name="region" placeholder="garage"/>
|
||||
<label>Bucket Endpoint</label>
|
||||
<input name="endpoint"/>
|
||||
<input type="submit" value="Create binary cache"/>
|
||||
<input name="endpoint_url" placeholder="https://cache.yourdomain.com"/>
|
||||
<input id="submit" type="submit" value="Create binary cache"/>
|
||||
</form>
|
||||
{{ /template }}
|
|
@ -1,6 +1,6 @@
|
|||
{{#> template js=js }}
|
||||
<h1>New user: {{ username }}</h1>
|
||||
<form id="key-form"><label>Key Name</label><input id="key-name"/><input type="submit" value="Enroll FIDO key"/></form>
|
||||
<form id="key-form"><label>Key Name</label><input id="key-name"/><input type="submit" id="submit" value="Enroll FIDO key"/></form>
|
||||
<table>
|
||||
<tr><th>KeyID</th></tr>
|
||||
{{#each keyids}}
|
||||
|
|
|
@ -11,11 +11,12 @@
|
|||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<p id="nom-nom-gc-txt">NOM NOM GC</p>
|
||||
<ul>
|
||||
<li><h1>Nom Nom GC</h1></li>
|
||||
<li><a href="/">Home</a></li>
|
||||
<li><a href="/projects">Projects</a></li>
|
||||
<li><a href="/login">Login</a></li>
|
||||
<li><img id="logo" src="/static/malix.webp" alt="logo"/><p id="logo-txt">Malix is eating your cache</p></li>
|
||||
<li><a href="/">HOME</a></li>
|
||||
<li><a href="/projects">PROJECTS</a></li>
|
||||
<li><a href="/login">LOGIN</a></li>
|
||||
</nav>
|
||||
<main>
|
||||
<div id="main-container">
|
||||
|
|
|
@ -41,9 +41,7 @@ function encodeSolvedChallenge(solvedChallenge) {
|
|||
|
||||
async function finish_auth (challengeUuid, solvedChallenge) {
|
||||
// Encode challenge response
|
||||
console.log(solvedChallenge);
|
||||
const encodedSolvedChallenge = encodeSolvedChallenge(solvedChallenge);
|
||||
console.log(encodedSolvedChallenge);
|
||||
const resp = await fetch("/login/finish", {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({uuid: challengeUuid, challenge: encodedSolvedChallenge}),
|
||||
|
@ -64,5 +62,6 @@ async function perform_webauthn_dance () {
|
|||
button.addEventListener("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
await perform_webauthn_dance();
|
||||
window.location = "/";
|
||||
});
|
||||
}) ();
|
||||
|
|
|
@ -74,10 +74,12 @@ async fn run_test_db(db: &TestDB) -> Result<()> {
|
|||
access_key: "access key".to_string(),
|
||||
secret_key: "secret key".to_string(),
|
||||
region: "reg-01".to_string(),
|
||||
endpoint_url: "localhost:"
|
||||
};
|
||||
state.create_binary_cache(&binary_cache).await?;
|
||||
let project = Project {
|
||||
name: "super-duper-project".to_string()
|
||||
name: "super-duper-project".to_string(),
|
||||
latest_closure_generation: 0
|
||||
};
|
||||
state.create_project(&binary_cache, &project).await?;
|
||||
let token = state.create_project_token(&project).await?;
|
||||
|
|
Loading…
Reference in a new issue