diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e82fdca..9eb5a45 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,30 +12,21 @@ env: REGISTRY: ghcr.io jobs: - rustfmt: - name: rustfmt - strategy: - matrix: - rust: ["stable"] + lint: + name: Lint and test runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v2 - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: ${{ matrix.rust }} - components: rustfmt - override: true - - name: Check formatting - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check + uses: actions/checkout@v4 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + - uses: Swatinem/rust-cache@v2 + - run: cargo check --all-targets --all-features + - run: cargo test --verbose -- --nocapture docker-build-and-push: + name: Docker build runs-on: ubuntu-latest + needs: lint permissions: contents: read packages: write @@ -58,72 +49,3 @@ jobs: with: push: true tags: ghcr.io/${{ github.repository_owner }}/graphix:latest - - build: - name: Build - strategy: - fail-fast: false - matrix: - rust: ["stable"] - runs-on: ubuntu-latest - - steps: - - name: Checkout sources - uses: actions/checkout@v2 - - name: Cache cargo registry - uses: actions/cache@v2 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - key: test-cargo-${{ hashFiles('**/Cargo.toml') }} - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: ${{ matrix.rust }} - override: true - - name: Build - uses: actions-rs/cargo@v1 - with: - command: build - - test: - name: Test - strategy: - fail-fast: false - matrix: - rust: ["stable"] - runs-on: ubuntu-latest - services: - postgres: - image: postgres - env: - POSTGRES_PASSWORD: postgres - POSTGRES_DB: graphix_test - ports: - - 5432:5432 - env: - GRAPHIX_TEST_DB_URL: "postgresql://postgres:postgres@localhost:5432/graphix_test" - - steps: - - name: Checkout sources - uses: actions/checkout@v2 - - name: Cache cargo registry - uses: actions/cache@v2 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - key: test-cargo-${{ hashFiles('**/Cargo.toml') }} - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: ${{ matrix.rust }} - override: true - - name: Test - uses: actions-rs/cargo@v1 - with: - command: test - args: --verbose -- --nocapture diff --git a/.gitignore b/.gitignore index c6d9f6b..38d583e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,5 @@ rustc-ice* ### Project specific ops/compose/data/* -/frontend/dist -frontend/graphql/api_schema.graphql +ops/compose/grafana/* +!ops/compose/grafana/data/grafana.db diff --git a/Cargo.lock b/Cargo.lock index c684a54..0f14177 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,24 +29,31 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.7.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "getrandom", + "cfg-if", "once_cell", "version_check", + "zerocopy", ] [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -64,47 +71,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.11" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -112,9 +120,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.70" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "arbitrary" @@ -142,16 +150,16 @@ checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a" [[package]] name = "async-graphql" -version = "7.0.1" +version = "7.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16926f97f683ff3b47b035cc79622f3d6a374730b07a5d9051e81e88b5f1904" +checksum = "d0808e3dc8be9cee801000b9261081cd7caae9935658be7e52d4df3d5c22bdce" dependencies = [ "async-graphql-derive", "async-graphql-parser", "async-graphql-value", "async-stream", "async-trait", - "base64 0.13.1", + "base64 0.22.1", "bytes", "chrono", "fast_chemail", @@ -160,8 +168,8 @@ dependencies = [ "futures-timer", "futures-util", "handlebars", - "http 1.0.0", - "indexmap", + "http 1.1.0", + "indexmap 2.2.6", "lru", "mime", "multer", @@ -180,9 +188,9 @@ dependencies = [ [[package]] name = "async-graphql-axum" -version = "7.0.1" +version = "7.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3415c9dbaf54397292da0bb81a907e2b989661ce068e4ccfebac33dc9e245e" +checksum = "d94b2673899046dbbb803dff9c400330f7908727f5edb99979c3d841136ee754" dependencies = [ "async-graphql", "async-trait", @@ -198,26 +206,26 @@ dependencies = [ [[package]] name = "async-graphql-derive" -version = "7.0.1" +version = "7.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a7349168b79030e3172a620f4f0e0062268a954604e41475eff082380fe505" +checksum = "ae80fb7b67deeae84441a9eb156359b99be7902d2d706f43836156eec69a8226" dependencies = [ "Inflector", "async-graphql-parser", - "darling 0.20.3", + "darling", "proc-macro-crate", "proc-macro2", "quote", "strum", - "syn 2.0.48", + "syn 2.0.66", "thiserror", ] [[package]] name = "async-graphql-parser" -version = "7.0.1" +version = "7.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fdc0adf9f53c2b65bb0ff5170cba1912299f248d0e48266f444b6f005deb1d" +checksum = "8f0fffb19cd96eb084428289f4568b5ad48df32f782f891f709db96384fbdeb2" dependencies = [ "async-graphql-value", "pest", @@ -227,12 +235,12 @@ dependencies = [ [[package]] name = "async-graphql-value" -version = "7.0.1" +version = "7.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cf4d4e86208f4f9b81a503943c07e6e7f29ad3505e6c9ce6431fe64dc241681" +checksum = "c224c93047a7197fe0f1d6eee98245ba6049706c6c04a372864557fb61495e94" dependencies = [ "bytes", - "indexmap", + "indexmap 2.2.6", "serde", "serde_json", ] @@ -256,41 +264,41 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e" +checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", "axum-core", "base64 0.21.7", "bytes", "futures-util", - "http 1.0.0", + "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.1.0", + "hyper 1.3.1", "hyper-util", "itoa", "matchit", @@ -304,7 +312,7 @@ dependencies = [ "serde_path_to_error", "serde_urlencoded", "sha1", - "sync_wrapper", + "sync_wrapper 1.0.1", "tokio", "tokio-tungstenite", "tower", @@ -322,13 +330,13 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.0.0", + "http 1.1.0", "http-body 1.0.0", "http-body-util", "mime", "pin-project-lite", "rustversion", - "sync_wrapper", + "sync_wrapper 0.1.2", "tower-layer", "tower-service", "tracing", @@ -336,9 +344,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -357,21 +365,21 @@ checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" [[package]] name = "base64" -version = "0.13.1" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" -version = "0.21.7" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bigdecimal" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06619be423ea5bb86c95f087d5707942791a08a85530df0db2209a3ecfb8bc9" +checksum = "9324c8014cd04590682b34f1e9448d38f0674d0f7b2dc553331016ef0e4e9ebc" dependencies = [ "autocfg", "libm", @@ -389,9 +397,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "block-buffer" @@ -402,45 +410,82 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bollard" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aed08d3adb6ebe0eff737115056652670ae290f177759aac19c30456135f94c" +dependencies = [ + "base64 0.22.1", + "bollard-stubs", + "bytes", + "futures-core", + "futures-util", + "hex", + "home", + "http 1.1.0", + "http-body-util", + "hyper 1.3.1", + "hyper-named-pipe", + "hyper-rustls", + "hyper-util", + "hyperlocal-next", + "log", + "pin-project-lite", + "rustls", + "rustls-native-certs", + "rustls-pemfile 2.1.2", + "rustls-pki-types", + "serde", + "serde_derive", + "serde_json", + "serde_repr", + "serde_urlencoded", + "thiserror", + "tokio", + "tokio-util", + "tower-service", + "url", + "winapi", +] + [[package]] name = "bollard-stubs" -version = "1.42.0-rc.3" +version = "1.44.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed59b5c00048f48d7af971b71f800fdf23e858844a6f9e4d32ca72e9399e7864" +checksum = "709d9aa1c37abb89d40f19f5d0ad6f0d88cb1581264e571c9350fc5bb89cf1c5" dependencies = [ "serde", + "serde_repr", "serde_with", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" dependencies = [ "serde", ] [[package]] name = "cc" -version = "1.0.83" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" [[package]] name = "cfg-if" @@ -450,9 +495,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.33" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -460,7 +505,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.0", + "windows-targets 0.52.5", ] [[package]] @@ -488,9 +533,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.18" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -498,9 +543,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.18" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstream", "anstyle", @@ -510,27 +555,27 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "combine" @@ -597,85 +642,50 @@ dependencies = [ [[package]] name = "darling" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core 0.13.4", - "darling_macro 0.13.4", -] - -[[package]] -name = "darling" -version = "0.20.3" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" dependencies = [ - "darling_core 0.20.3", - "darling_macro 0.20.3", -] - -[[package]] -name = "darling_core" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", + "darling_core", + "darling_macro", ] [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] name = "darling_macro" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" -dependencies = [ - "darling_core 0.13.4", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.20.3" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ - "darling_core 0.20.3", + "darling_core", "quote", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "data-encoding-macro" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20c01c06f5f429efdf2bae21eb67c28b3df3cf85b7dd2d8ef09c0838dac5d33e" +checksum = "f1559b6cba622276d6d63706db152618eeb15b89b3e4041446b05876e352e639" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -683,9 +693,9 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0047d07f2c89b17dd631c80450d69841a6b5d7fb17278cbc43d7e4cfcf2576f3" +checksum = "332d754c0af53bc87c108fed664d121ecf59207ec4196041f04d6ab9002ad33f" dependencies = [ "data-encoding", "syn 1.0.109", @@ -706,9 +716,9 @@ dependencies = [ [[package]] name = "deadpool-runtime" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63dfa964fe2a66f3fde91fc70b267fe193d822c7e603e2a675a49a7f46ad3f49" +checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" [[package]] name = "deranged" @@ -717,6 +727,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -734,12 +745,12 @@ dependencies = [ [[package]] name = "diesel" -version = "2.1.4" +version = "2.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62c6fcf842f17f8c78ecf7c81d75c5ce84436b41ee07e03f490fbb5f5a8731d8" +checksum = "ff236accb9a5069572099f0b350a92e9560e8e63a9b8d546162f4a5e03026bb2" dependencies = [ "bigdecimal", - "bitflags 2.4.2", + "bitflags 2.5.0", "byteorder", "chrono", "diesel_derives", @@ -796,14 +807,14 @@ dependencies = [ [[package]] name = "diesel_derives" -version = "2.1.2" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8337737574f55a468005a83499da720f20c65586241ffea339db9ecdfd2b44" +checksum = "14701062d6bed917b5c7103bdffaee1e4609279e240488ad24e7bd979ca6866c" dependencies = [ "diesel_table_macro_syntax", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] @@ -812,7 +823,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5" dependencies = [ - "syn 2.0.48", + "syn 2.0.66", ] [[package]] @@ -826,23 +837,55 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "docker_credential" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31951f49556e34d90ed28342e1df7e1cb7a229c4cab0aecc627b5d91edd41d07" +dependencies = [ + "base64 0.21.7", + "serde", + "serde_json", +] + [[package]] name = "dyn-clone" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "either" -version = "1.8.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -865,9 +908,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -890,15 +933,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" - -[[package]] -name = "finl_unicode" -version = "1.2.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fnv" @@ -986,7 +1023,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] @@ -1037,9 +1074,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -1069,7 +1106,6 @@ dependencies = [ "graphix_network_sg_client", "graphix_store", "hex", - "nanoid", "once_cell", "prometheus_exporter", "rand", @@ -1115,6 +1151,7 @@ dependencies = [ "schemars", "serde", "serde_json", + "strum", "uuid", ] @@ -1143,7 +1180,9 @@ version = "0.1.0" dependencies = [ "anyhow", "async-graphql", + "async-graphql-axum", "async-trait", + "axum", "chrono", "derive_more", "diesel", @@ -1167,7 +1206,9 @@ dependencies = [ "serde", "serde_json", "serde_yaml", + "sha2", "tokio", + "tower-service", "tracing", "url", "uuid", @@ -1196,9 +1237,9 @@ version = "0.1.0" dependencies = [ "anyhow", "async-graphql", - "async-trait", "bigdecimal", "chrono", + "derive_more", "diesel", "diesel-async", "diesel_async_migrations", @@ -1208,6 +1249,8 @@ dependencies = [ "hex", "serde", "serde_json", + "sha2", + "strum", "testcontainers", "testcontainers-modules", "tokio", @@ -1253,7 +1296,7 @@ checksum = "a40f793251171991c4eb75bd84bc640afa8b68ff6907bc89d3b712a22f700506" dependencies = [ "graphql-introspection-query", "graphql-parser", - "heck", + "heck 0.4.1", "lazy_static", "proc-macro2", "quote", @@ -1275,36 +1318,17 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http 0.2.11", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "h2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 1.0.0", - "indexmap", + "http 0.2.12", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -1313,9 +1337,9 @@ dependencies = [ [[package]] name = "handlebars" -version = "4.5.0" +version = "5.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faa67bab9ff362228eb3d00bd024a4965d8231bbb7921167f0cfa66c6626b225" +checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b" dependencies = [ "log", "pest", @@ -1330,15 +1354,16 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash", -] [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] [[package]] name = "heck" @@ -1346,11 +1371,17 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" -version = "0.3.4" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1367,11 +1398,20 @@ dependencies = [ "digest", ] +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -1380,9 +1420,9 @@ dependencies = [ [[package]] name = "http" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -1396,7 +1436,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http 0.2.11", + "http 0.2.12", "pin-project-lite", ] @@ -1407,18 +1447,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ "bytes", - "http 1.0.0", + "http 1.1.0", ] [[package]] name = "http-body-util" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" dependencies = [ "bytes", - "futures-util", - "http 1.0.0", + "futures-core", + "http 1.1.0", "http-body 1.0.0", "pin-project-lite", ] @@ -1445,8 +1485,8 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.3.24", - "http 0.2.11", + "h2", + "http 0.2.12", "http-body 0.4.6", "httparse", "httpdate", @@ -1461,21 +1501,56 @@ dependencies = [ [[package]] name = "hyper" -version = "1.1.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.2", - "http 1.0.0", + "http 1.1.0", "http-body 1.0.0", "httparse", "httpdate", "itoa", "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-named-pipe" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278" +dependencies = [ + "hex", + "hyper 1.3.1", + "hyper-util", + "pin-project-lite", "tokio", + "tower-service", + "winapi", +] + +[[package]] +name = "hyper-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.3.1", + "hyper-util", + "log", + "rustls", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", ] [[package]] @@ -1493,27 +1568,44 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdea9aac0dbe5a9240d68cfd9501e2db94222c6dc06843e06640b9e07f0fdc67" +checksum = "3d8d52be92d09acc2e01dddb7fde3ad983fc6489c7db4837e605bc3fca4cb63e" dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.0.0", + "http 1.1.0", "http-body 1.0.0", - "hyper 1.1.0", + "hyper 1.3.1", "pin-project-lite", "socket2", "tokio", + "tower", + "tower-service", "tracing", ] +[[package]] +name = "hyperlocal-next" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acf569d43fa9848e510358c07b80f4adf34084ddc28c6a4a651ee8474c070dcc" +dependencies = [ + "hex", + "http-body-util", + "hyper 1.3.1", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + [[package]] name = "iana-time-zone" -version = "0.1.59" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1550,12 +1642,23 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "serde", ] @@ -1574,26 +1677,32 @@ dependencies = [ "serde", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.67" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1606,9 +1715,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.152" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libm" @@ -1616,17 +1725,27 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.5.0", + "libc", +] + [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1634,17 +1753,17 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "lru" -version = "0.7.8" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" dependencies = [ - "hashbrown 0.12.3", + "hashbrown 0.14.5", ] [[package]] @@ -1674,9 +1793,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mime" @@ -1686,18 +1805,18 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", @@ -1706,16 +1825,15 @@ dependencies = [ [[package]] name = "multer" -version = "3.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15d522be0a9c3e46fd2632e272d178f56387bdb5c9fbb3a36c649062e9b5219" +checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 1.0.0", + "http 1.1.0", "httparse", - "log", "memchr", "mime", "spin", @@ -1747,15 +1865,6 @@ dependencies = [ "unsigned-varint 0.7.2", ] -[[package]] -name = "nanoid" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8" -dependencies = [ - "rand", -] - [[package]] name = "native-tls" version = "0.2.11" @@ -1786,30 +1895,34 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" dependencies = [ - "autocfg", "num-integer", "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -1841,11 +1954,11 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" -version = "0.10.63" +version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c9d69dd87a29568d4d017cfe8ec518706046a05184e5aea92d0af890b803c8" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "cfg-if", "foreign-types", "libc", @@ -1862,7 +1975,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] @@ -1873,9 +1986,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.99" +version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e1bf214306098e4832460f797824c05d25aacdf896f64a985fb0fd992454ae" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", @@ -1883,6 +1996,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "overload" version = "0.1.1" @@ -1891,9 +2010,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -1901,15 +2020,40 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.1", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.5", +] + +[[package]] +name = "parse-display" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914a1c2265c98e2446911282c6ac86d8524f495792c38c5bd884f80499c7538a" +dependencies = [ + "parse-display-derive", + "regex", + "regex-syntax 0.8.3", +] + +[[package]] +name = "parse-display-derive" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ae7800a4c974efd12df917266338e79a7a74415173caf7e70aa0a0707345281" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "regex-syntax 0.8.3", + "structmeta", + "syn 2.0.66", ] [[package]] @@ -1920,9 +2064,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.6" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f200d8d83c44a45b21764d1916299752ca035d15ecd46faca3e9a2a2bf6ad06" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" dependencies = [ "memchr", "thiserror", @@ -1931,9 +2075,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.6" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcd6ab1236bbdb3a49027e920e693192ebfe8913f6d60e294de57463a493cfde" +checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" dependencies = [ "pest", "pest_generator", @@ -1941,22 +2085,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.6" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a31940305ffc96863a735bef7c7994a00b325a7138fdbc5bda0f1a0476d3275" +checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] name = "pest_meta" -version = "2.7.6" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ff62f5259e53b78d1af898941cdcdccfae7385cf7d793a6e55de5d05bb4b7d" +checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" dependencies = [ "once_cell", "pest", @@ -1983,29 +2127,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -2015,9 +2159,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "postgres-protocol" @@ -2071,28 +2215,27 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.3.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "once_cell", "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" dependencies = [ "unicode-ident", ] [[package]] name = "prometheus" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" +checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" dependencies = [ "cfg-if", "fnv", @@ -2140,9 +2283,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -2197,16 +2340,36 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags 2.5.0", +] + +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "regex" -version = "1.9.4" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.7", - "regex-syntax 0.7.5", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", ] [[package]] @@ -2220,13 +2383,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.7" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.5", + "regex-syntax 0.8.3", ] [[package]] @@ -2237,23 +2400,23 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" -version = "0.11.23" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64 0.21.7", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2 0.3.24", - "http 0.2.11", + "h2", + "http 0.2.12", "http-body 0.4.6", "hyper 0.14.28", "hyper-tls", @@ -2265,9 +2428,11 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper 0.1.2", "system-configuration", "tokio", "tokio-native-tls", @@ -2285,11 +2450,26 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0" +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" @@ -2302,28 +2482,91 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.30" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.1.2", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +dependencies = [ + "base64 0.22.1", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + +[[package]] +name = "rustls-webpki" +version = "0.102.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" @@ -2345,9 +2588,9 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" dependencies = [ "chrono", "dyn-clone", @@ -2359,14 +2602,14 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] @@ -2387,11 +2630,11 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -2400,9 +2643,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", @@ -2410,15 +2653,15 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] @@ -2434,31 +2677,31 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] name = "serde_derive_internals" -version = "0.26.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -2467,14 +2710,25 @@ dependencies = [ [[package]] name = "serde_path_to_error" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" dependencies = [ "itoa", "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -2489,33 +2743,41 @@ dependencies = [ [[package]] name = "serde_with" -version = "1.14.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.6", "serde", + "serde_derive", + "serde_json", "serde_with_macros", + "time", ] [[package]] name = "serde_with_macros" -version = "1.5.2" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" dependencies = [ - "darling 0.13.4", + "darling", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] name = "serde_yaml" -version = "0.9.31" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adf8a49373e98a4c5f0ceb5d05aa7c648d75f63774981ed95b7c7443bbd50c6e" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap", + "indexmap 2.2.6", "itoa", "ryu", "serde", @@ -2555,9 +2817,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -2579,18 +2841,18 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2607,41 +2869,64 @@ checksum = "d7beae5182595e9a8b683fa98c4317f956c9a2dec3b9716990d20023cc60c766" [[package]] name = "stringprep" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ - "finl_unicode", "unicode-bidi", "unicode-normalization", + "unicode-properties", ] [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "structmeta" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "2e1575d8d40908d70f6fd05537266b90ae71b15dbbe7a8b7dffa2b759306d329" +dependencies = [ + "proc-macro2", + "quote", + "structmeta-derive", + "syn 2.0.66", +] + +[[package]] +name = "structmeta-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] [[package]] name = "strum" -version = "0.25.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.25.3" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] @@ -2663,9 +2948,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -2678,6 +2963,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + [[package]] name = "system-configuration" version = "0.5.1" @@ -2701,68 +2992,76 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.9.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", "rustix", "windows-sys 0.52.0", ] [[package]] name = "testcontainers" -version = "0.15.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d2931d7f521af5bae989f716c3fa43a6af9af7ec7a5e21b59ae40878cec00" +checksum = "025e0ac563d543e0354d984540e749859a83dbe5c0afb8d458dc48d91cef2d6a" dependencies = [ + "async-trait", + "bollard", "bollard-stubs", + "bytes", + "dirs", + "docker_credential", "futures", - "hex", - "hmac", "log", - "rand", + "memchr", + "parse-display", "serde", "serde_json", - "sha2", + "serde_with", + "thiserror", + "tokio", + "tokio-stream", + "tokio-util", + "url", ] [[package]] name = "testcontainers-modules" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd5c0d66f296de264c0593f42ea2ef2ad3ff9a62bc946a5d4e8d21be1317c505" +checksum = "87dc086b8c791e5696de6de4e0d79de2cb9f8a1ac4552d46d6211a42d81d6d0f" dependencies = [ "testcontainers", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -2770,12 +3069,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.31" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -2790,10 +3090,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -2827,9 +3128,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.1" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -2852,7 +3153,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] @@ -2891,11 +3192,22 @@ dependencies = [ "whoami", ] +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", @@ -2916,9 +3228,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", @@ -2926,22 +3238,21 @@ dependencies = [ "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" [[package]] name = "toml_edit" -version = "0.19.15" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap", + "indexmap 2.2.6", "toml_datetime", "winnow", ] @@ -2994,7 +3305,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] @@ -3074,7 +3385,7 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http 1.0.0", + "http 1.1.0", "httparse", "log", "rand", @@ -3104,19 +3415,25 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" + [[package]] name = "unreachable" version = "1.0.0" @@ -3128,9 +3445,9 @@ dependencies = [ [[package]] name = "unsafe-libyaml" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "unsigned-varint" @@ -3144,6 +3461,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -3170,9 +3493,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ "getrandom", "serde", @@ -3217,11 +3540,17 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -3229,24 +3558,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.40" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -3256,9 +3585,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3266,28 +3595,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.67" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -3295,11 +3624,12 @@ dependencies = [ [[package]] name = "whoami" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" +checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" dependencies = [ - "wasm-bindgen", + "redox_syscall 0.4.1", + "wasite", "web-sys", ] @@ -3331,7 +3661,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.5", ] [[package]] @@ -3349,7 +3679,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.5", ] [[package]] @@ -3369,17 +3699,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -3390,9 +3721,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -3402,9 +3733,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -3414,9 +3745,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -3426,9 +3763,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -3438,9 +3775,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -3450,9 +3787,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -3462,15 +3799,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" -version = "0.5.35" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1931d78a9c73861da0134f453bb1f790ce49b2e30eba8410b4b79bac72b46a2d" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ "memchr", ] @@ -3484,3 +3821,29 @@ dependencies = [ "cfg-if", "windows-sys 0.48.0", ] + +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/Cargo.toml b/Cargo.toml index 058cde3..9948c66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,6 @@ futures = "0.3.18" graphql_client = "0.13" hex = "0.4.3" itertools = "0.12" -nanoid = "0.4.0" num-traits = "0.2" once_cell = "1.9.0" prometheus = { version = "0.13", default-features = false } @@ -33,8 +32,10 @@ schemars = "0.8" serde = "1" serde_json = "1" serde_yaml = "0.9" -testcontainers = "0.15" -testcontainers-modules = "0.3" +sha2 = "0.10" +strum = { version = "0.26", features = ["derive"] } +testcontainers = "0.17" +testcontainers-modules = "0.5" thiserror = "1" tokio = "1.14.0" tracing = "0.1.29" diff --git a/bruno/Assign a human-readable name to a deployment.bru b/bruno/Assign a human-readable name to a deployment.bru new file mode 100644 index 0000000..3c189c0 --- /dev/null +++ b/bruno/Assign a human-readable name to a deployment.bru @@ -0,0 +1,28 @@ +meta { + name: Assign a human-readable name to a deployment + type: graphql + seq: 5 +} + +post { + url: {{ _.url }} + body: graphql + auth: none +} + +headers { + User-Agent: Insomnia/2023.5.7 + Content-Type: application/json +} + +body:graphql { + mutation { + setDeploymentName( + deploymentIpfsCid: "Qmadj8x9km1YEyKmRnJ6EkC2zpJZFCfTyTZpuqC3j6e1QH" + name: "premia.eth/premia-mainnet" + ) { + id + } + } + +} diff --git a/bruno/Delete a network and all related data.bru b/bruno/Delete a network and all related data.bru new file mode 100644 index 0000000..e4b5c93 --- /dev/null +++ b/bruno/Delete a network and all related data.bru @@ -0,0 +1,23 @@ +meta { + name: Delete a network and all related data + type: graphql + seq: 6 +} + +post { + url: {{ _.url }} + body: graphql + auth: none +} + +headers { + User-Agent: Insomnia/2023.5.7 + Content-Type: application/json +} + +body:graphql { + mutation { + deleteNetwork(network: "testnet") + } + +} diff --git a/bruno/Fetch a divergence investigation report.bru b/bruno/Fetch a divergence investigation report.bru new file mode 100644 index 0000000..79d218b --- /dev/null +++ b/bruno/Fetch a divergence investigation report.bru @@ -0,0 +1,21 @@ +meta { + name: Fetch a divergence investigation report + type: graphql + seq: 8 +} + +post { + url: {{ _.url }} + body: graphql + auth: none +} + +headers { + Content-Type: application/json +} + +body:graphql { + { + poiCrossCheckReport(requestId: "9b587618-9f25-4f96-b435-a3b9f94dc9f2") + } +} diff --git a/bruno/Launch a divergence investigation.bru b/bruno/Launch a divergence investigation.bru new file mode 100644 index 0000000..16a688e --- /dev/null +++ b/bruno/Launch a divergence investigation.bru @@ -0,0 +1,42 @@ +meta { + name: Launch a divergence investigation + type: graphql + seq: 7 +} + +post { + url: {{ _.url }} + body: graphql + auth: none +} + +headers { + Content-Type: application/json +} + +body:graphql { + mutation { + launchDivergenceInvestigation( + req: { + pois: ["foo", "bar"] + queryBlockCaches: true + queryEthCallCaches: false + queryEntityChanges: true + } + ) { + uuid + status + bisectionRuns { + divergenceBlockBounds { + lowerBound { + number + } + upperBound { + number + } + } + } + } + } + +} diff --git a/bruno/Poll indexer-s PoIs popularity -a-k-a- -PoI agreement ratios--.bru b/bruno/Poll indexer-s PoIs popularity -a-k-a- -PoI agreement ratios--.bru new file mode 100644 index 0000000..e29bb5e --- /dev/null +++ b/bruno/Poll indexer-s PoIs popularity -a-k-a- -PoI agreement ratios--.bru @@ -0,0 +1,30 @@ +meta { + name: Poll indexer-s PoIs popularity -a-k-a- -PoI agreement ratios-- + type: graphql + seq: 4 +} + +post { + url: {{ _.url }} + body: graphql + auth: none +} + +headers { + Content-Type: application/json +} + +body:graphql { + { + poiAgreementRatios(indexerName: "testnet-indexer-03") { + poi + deployment { + id + } + nAgreeingIndexers + nDisagreeingIndexers + hasConsensus + inConsensus + } + } +} diff --git a/bruno/Query PoIs.bru b/bruno/Query PoIs.bru new file mode 100644 index 0000000..ae5dafd --- /dev/null +++ b/bruno/Query PoIs.bru @@ -0,0 +1,38 @@ +meta { + name: Query PoIs + type: graphql + seq: 3 +} + +post { + url: {{ _.url }} + body: graphql + auth: none +} + +headers { + Content-Type: application/json +} + +body:graphql { + { + proofsOfIndexing(request: { + deployments: ["Qmadj8x9km1YEyKmRnJ6EkC2zpJZFCfTyTZpuqC3j6e1QH"], + blockRange: {start: 1000}, + limit: 100 + }) { + hash + block { + hash + number + } + allocatedTokens + deployment { + id + } + indexer { + id + } + } + } +} diff --git a/bruno/Query deployments.bru b/bruno/Query deployments.bru new file mode 100644 index 0000000..9be4d93 --- /dev/null +++ b/bruno/Query deployments.bru @@ -0,0 +1,33 @@ +meta { + name: Query deployments + type: graphql + seq: 1 +} + +post { + url: {{ _.url }} + body: graphql + auth: none +} + +headers { + Content-Type: application/json +} + +body:graphql { + { + deployments( + filter: { + network: "mainnet" + ipfsCid: "Qmadj8x9km1YEyKmRnJ6EkC2zpJZFCfTyTZpuqC3j6e1QH" + #name: "premia.eth/premia-mainnet" + limit: 100 + } + ) { + id + name + networkName + } + } + +} diff --git a/bruno/Query indexers.bru b/bruno/Query indexers.bru new file mode 100644 index 0000000..a7f2223 --- /dev/null +++ b/bruno/Query indexers.bru @@ -0,0 +1,30 @@ +meta { + name: Query indexers + type: graphql + seq: 2 +} + +post { + url: {{ _.url }} + body: graphql + auth: none +} + +headers { + Content-Type: application/json +} + +body:graphql { + { + indexers( + filter: { + address: "0x87eba079059b75504c734820d6cf828476754b83" + limit: 100 + } + ) { + id + allocatedTokens + } + } + +} diff --git a/bruno/bruno.json b/bruno/bruno.json new file mode 100644 index 0000000..a1de707 --- /dev/null +++ b/bruno/bruno.json @@ -0,0 +1,9 @@ +{ + "version": "1", + "name": "Graphix", + "type": "collection", + "ignore": [ + "node_modules", + ".git" + ] +} \ No newline at end of file diff --git a/crates/autogen_config_json_schema/build.rs b/crates/autogen_config_json_schema/build.rs index 328b7c5..c69def5 100644 --- a/crates/autogen_config_json_schema/build.rs +++ b/crates/autogen_config_json_schema/build.rs @@ -6,11 +6,6 @@ use graphix_lib::config::Config; use schemars::schema_for; fn main() -> std::io::Result<()> { - // We're only interested in re-generating the API schema if build - // dependencies change or the build script itself does. - // See . - println!("cargo:rerun-if-changed=build.rs"); - let out_path = env::current_dir()?.join("schema.json"); let mut f = File::create(&out_path)?; diff --git a/crates/autogen_config_json_schema/schema.json b/crates/autogen_config_json_schema/schema.json index bb2eef7..d740b0f 100644 --- a/crates/autogen_config_json_schema/schema.json +++ b/crates/autogen_config_json_schema/schema.json @@ -69,6 +69,7 @@ "type": "string" }, "ChainConfig": { + "description": "Chain-specific configuration.", "type": "object", "properties": { "avgBlockTimeInMsecs": { @@ -77,6 +78,7 @@ "minimum": 0.0 }, "blockExplorerUrlTemplateForBlock": { + "description": "URL to a block explorer for this chain, with `{block}` as a placeholder for the block number.", "default": null, "anyOf": [ { diff --git a/crates/autogen_graphql_schema/api_schema.graphql b/crates/autogen_graphql_schema/api_schema.graphql index 3558b89..297b5d8 100644 --- a/crates/autogen_graphql_schema/api_schema.graphql +++ b/crates/autogen_graphql_schema/api_schema.graphql @@ -1,5 +1,15 @@ # AUTOGENERATED. DO NOT MODIFY. ALL CHANGES WILL BE LOST. +enum ApiKeyPermissionLevel { + ADMIN +} + +type ApiKeyPublicMetadata { + publicPrefix: String! + notes: String + permissionLevel: ApiKeyPermissionLevel! +} + """ Metadata that was collected during a bisection run. """ @@ -222,7 +232,7 @@ type MutationRoot { """ queryBlockCaches: Boolean! = true, """ - Indicates whether to collect `graph-node`'s eth call cache contents during bisection runs to include in the report. + Indicates whether to collect `graph-node`'s ETH call cache contents during bisection runs to include in the report. """ queryEthCallCaches: Boolean! = true, """ @@ -230,6 +240,28 @@ type MutationRoot { """ queryEntityChanges: Boolean! = true ): DivergenceInvestigationReport! + """ + Create a new API key with the given permission level. You'll need to + authenticate with another API key with the `admin` permission level to + do this. + """ + createApiKey( + """ + Permission level of the API key. Use `admin` for full access. + """ + permissionLevel: ApiKeyPermissionLevel!, + """ + Not-encrypted notes to store in the database alongside the API key, to be used for debugging or identification purposes. + """ + notes: String = null + ): NewlyCreatedApiKey! + deleteApiKey(apiKey: String!): Boolean! + modifyApiKey( apiKey: String!, + """ + Not-encrypted notes to store in the database alongside the API key, to be used for debugging or identification purposes. + """ + notes: String, permissionLevel: ApiKeyPermissionLevel! + ): Boolean! setDeploymentName(deploymentIpfsCid: String!, name: String!): Deployment! """ Completely deletes a network and all related data (PoIs, indexers, subgraphs, etc.). @@ -258,6 +290,12 @@ type Network { caip2: String } +type NewlyCreatedApiKey { + apiKey: String! + notes: String + permissionLevel: ApiKeyPermissionLevel! +} + """ A block number that may or may not also have an associated hash. """ @@ -405,6 +443,7 @@ type QueryRoot { subgraph deployment. """ liveProofsOfIndexing(filter: PoisQuery!): [ProofOfIndexing!]! + apiKeys: [ApiKeyPublicMetadata!]! poiAgreementRatios(indexerAddress: HexString!): [PoiAgreementRatio!]! divergenceInvestigationReport( """ @@ -423,7 +462,7 @@ type QueryRoot { type SubgraphDeployment { """ - IPFS CID of the subgraph deployment. + IPFS CID of the subgraph deployment manifest e.g. `Qm...`. """ cid: IpfsCid! """ diff --git a/crates/autogen_graphql_schema/build.rs b/crates/autogen_graphql_schema/build.rs index 4c3f8b8..216a5f2 100644 --- a/crates/autogen_graphql_schema/build.rs +++ b/crates/autogen_graphql_schema/build.rs @@ -5,13 +5,7 @@ use std::io::*; use graphix_lib::graphql_api::api_schema_builder; fn main() -> std::io::Result<()> { - // We're only interested in re-generating the API schema if build - // dependencies change or the build script itself does. - // See . - println!("cargo:rerun-if-changed=build.rs"); - let path = env::current_dir()?.join("api_schema.graphql"); - let mut f = File::create(&path)?; f.write_all(b"# AUTOGENERATED. DO NOT MODIFY. ALL CHANGES WILL BE LOST.\n\n")?; diff --git a/crates/common_types/Cargo.toml b/crates/common_types/Cargo.toml index 5f042c2..a93fdca 100644 --- a/crates/common_types/Cargo.toml +++ b/crates/common_types/Cargo.toml @@ -15,6 +15,7 @@ quickcheck = { workspace = true } schemars = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } +strum = { workspace = true } uuid = { workspace = true } [dev-dependencies] diff --git a/crates/common_types/src/api_key_permission_level.rs b/crates/common_types/src/api_key_permission_level.rs new file mode 100644 index 0000000..d646417 --- /dev/null +++ b/crates/common_types/src/api_key_permission_level.rs @@ -0,0 +1,43 @@ +use diesel::deserialize::{FromSql, FromSqlRow}; +use diesel::expression::AsExpression; +use diesel::pg::{Pg, PgValue}; +use diesel::serialize::ToSql; +use diesel::sql_types; + +#[derive( + Debug, + Copy, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + AsExpression, + FromSqlRow, + async_graphql::Enum, +)] +#[diesel(sql_type = sql_types::Integer)] +#[repr(i32)] +pub enum ApiKeyPermissionLevel { + Admin, +} + +impl ToSql for ApiKeyPermissionLevel { + fn to_sql<'b>( + &'b self, + out: &mut diesel::serialize::Output<'b, '_, Pg>, + ) -> diesel::serialize::Result { + match self { + ApiKeyPermissionLevel::Admin => >::to_sql(&1, out), + } + } +} + +impl FromSql for ApiKeyPermissionLevel { + fn from_sql(bytes: PgValue<'_>) -> diesel::deserialize::Result { + match i32::from_sql(bytes)? { + 1 => Ok(ApiKeyPermissionLevel::Admin), + _ => Err(anyhow::anyhow!("invalid permission level").into()), + } + } +} diff --git a/crates/common_types/src/lib.rs b/crates/common_types/src/lib.rs index 9dad7e8..a8cb283 100644 --- a/crates/common_types/src/lib.rs +++ b/crates/common_types/src/lib.rs @@ -3,10 +3,12 @@ //! A few of these are shared with database models as well. Should we keep them //! separate? It would be cleaner, but at the cost of some code duplication. +mod api_key_permission_level; mod hex_string; pub mod inputs; mod ipfs_cid; +pub use api_key_permission_level::ApiKeyPermissionLevel; use async_graphql::*; use chrono::NaiveDateTime; pub use divergence_investigation::*; diff --git a/crates/graphix/Cargo.toml b/crates/graphix/Cargo.toml index 2959a61..256ac3a 100644 --- a/crates/graphix/Cargo.toml +++ b/crates/graphix/Cargo.toml @@ -15,7 +15,6 @@ graphix_indexer_client = { path = "../indexer_client" } graphix_lib = { path = "../graphix_lib" } graphix_network_sg_client = { path = "../network_sg_client" } graphix_store = { path = "../store" } -nanoid = { workspace = true } prometheus_exporter = { workspace = true } serde_json = { workspace = true } thiserror = { workspace = true } diff --git a/crates/graphix/src/bisect.rs b/crates/graphix/src/bisect.rs index 1d00978..eafc081 100644 --- a/crates/graphix/src/bisect.rs +++ b/crates/graphix/src/bisect.rs @@ -11,7 +11,7 @@ use graphix_indexer_client::{ IndexerClient, IndexerId, PoiRequest, ProofOfIndexing, SubgraphDeployment, }; use graphix_lib::graphql_api::api_types::{self, Indexer}; -use graphix_lib::graphql_api::ApiSchemaContext; +use graphix_lib::graphql_api::ServerState; use graphix_store::models::DivergenceInvestigationRequest; use graphix_store::Store; use thiserror::Error; @@ -182,7 +182,7 @@ pub enum DivergenceInvestigationError { pub async fn handle_divergence_investigation_requests( store: &Store, indexers: watch::Receiver>>, - ctx: &ApiSchemaContext, + ctx: &ServerState, ) -> anyhow::Result<()> { loop { debug!("Checking for new divergence investigation requests"); @@ -242,7 +242,7 @@ impl PoiWithRelatedData { poi_bytes: &PoiBytes, store: &Store, indexers: &[Arc], - ctx: &ApiSchemaContext, + ctx: &ServerState, ) -> anyhow::Result> { let Some(poi_model) = store.poi(poi_bytes).await? else { return Ok(None); @@ -287,7 +287,7 @@ async fn handle_divergence_investigation_request_pair( req_uuid: &Uuid, poi1_s: &PoiBytes, poi2_s: &PoiBytes, - ctx: &ApiSchemaContext, + ctx: &ServerState, ) -> BisectionRunReport { debug!(?req_uuid, poi1 = %poi1_s, poi2 = %poi2_s, "Bisecting Pois"); @@ -380,7 +380,7 @@ async fn handle_divergence_investigation_request( req_uuid: &Uuid, req_contents: DivergenceInvestigationRequest, indexers: watch::Receiver>>, - ctx: &ApiSchemaContext, + ctx: &ServerState, ) -> DivergenceInvestigationReport { let mut report = DivergenceInvestigationReport { uuid: req_uuid.clone(), diff --git a/crates/graphix/src/main.rs b/crates/graphix/src/main.rs index ac63718..83d5bdf 100644 --- a/crates/graphix/src/main.rs +++ b/crates/graphix/src/main.rs @@ -9,16 +9,12 @@ use std::path::PathBuf; use std::sync::Arc; use std::time::Duration; -use async_graphql::http::GraphiQLSource; -use async_graphql_axum::GraphQL; -use axum::response::IntoResponse; -use axum::Router; use clap::Parser; use graphix_indexer_client::{IndexerClient, IndexerId}; use graphix_lib::config::Config; -use graphix_lib::graphql_api::{self, ApiSchemaContext}; +use graphix_lib::graphql_api::{axum_router, ServerState}; use graphix_lib::indexing_loop::{query_indexing_statuses, query_proofs_of_indexing}; -use graphix_lib::{config, metrics, PrometheusExporter, GRAPHIX_VERSION}; +use graphix_lib::{config, metrics, PrometheusExporter}; use graphix_store::{models, PoiLiveness, Store}; use prometheus_exporter::prometheus; use tokio::net::TcpListener; @@ -53,7 +49,7 @@ async fn main() -> anyhow::Result<()> { // Listen to requests forever. axum::serve( TcpListener::bind((Ipv4Addr::UNSPECIFIED, config.graphql.port)).await?, - axum_server(config).await?, + axum_router(config).await?, ) .await?; @@ -70,7 +66,7 @@ async fn main() -> anyhow::Result<()> { info!("Initializing bisect request handler"); let store_clone = store.clone(); let (tx_indexers, rx_indexers) = watch::channel(vec![]); - let ctx = ApiSchemaContext::new(store_clone.clone(), config.clone()); + let ctx = ServerState::new(store_clone.clone(), config.clone()); { let networks: Vec = config @@ -148,30 +144,3 @@ fn deduplicate_indexers(indexers: &[Arc]) -> Vec anyhow::Result> { - use axum::routing::get; - - let store = Store::new(config.database_url.as_str()).await?; - let api_schema_ctx = graphql_api::ApiSchemaContext::new(store.clone(), config.clone()); - let api_schema = graphql_api::api_schema(api_schema_ctx); - - Ok(axum::Router::new() - .route( - "/", - get(|| async { - format!( - "Welcome to Graphix v{}. Go to /graphql to use the playground.", - GRAPHIX_VERSION - ) - }), - ) - .route( - "/graphql", - get(graphiql_route).post_service(GraphQL::new(api_schema)), - )) -} - -async fn graphiql_route() -> impl IntoResponse { - axum::response::Html(GraphiQLSource::build().endpoint("/graphql").finish()) -} diff --git a/crates/graphix_lib/Cargo.toml b/crates/graphix_lib/Cargo.toml index 44d562c..493a4f6 100644 --- a/crates/graphix_lib/Cargo.toml +++ b/crates/graphix_lib/Cargo.toml @@ -6,7 +6,9 @@ edition = "2021" [dependencies] anyhow = { workspace = true } async-graphql = { workspace = true, features = ["dataloader"] } +async-graphql-axum = { workspace = true } async-trait = { workspace = true, optional = true } +axum = { workspace = true } chrono = { workspace = true, features = ["serde"] } derive_more = { workspace = true } diesel = { workspace = true } @@ -25,7 +27,9 @@ schemars = { workspace = true, features = ["chrono", "url"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } serde_yaml = { workspace = true } +sha2 = { workspace = true } tokio = { workspace = true, features = ["full"] } +tower-service = "0.3" tracing = { workspace = true } uuid = { workspace = true, features = ["serde"] } url = { workspace = true, features = ["serde"] } diff --git a/crates/graphix_lib/src/config.rs b/crates/graphix_lib/src/config.rs index 49367bd..babb5f4 100644 --- a/crates/graphix_lib/src/config.rs +++ b/crates/graphix_lib/src/config.rs @@ -45,12 +45,17 @@ pub struct ChainSpeedConfig { pub avg_block_time_in_msecs: u64, } +/// Chain-specific configuration. #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] #[serde(rename_all = "camelCase")] pub struct ChainConfig { pub caip2: Option, + /// Specifies an approximation of the standard block time for this chain, to + /// approximate block timestamps. #[serde(flatten, default)] pub speed: Option, + /// URL to a block explorer for this chain, with `{block}` as a placeholder + /// for the block number. #[serde(default)] pub block_explorer_url_template_for_block: Option, } diff --git a/crates/graphix_lib/src/graphql_api/api_types.rs b/crates/graphix_lib/src/graphql_api/api_types.rs index 5bad9c2..e31e2f5 100644 --- a/crates/graphix_lib/src/graphql_api/api_types.rs +++ b/crates/graphix_lib/src/graphql_api/api_types.rs @@ -1,10 +1,10 @@ use async_graphql::{ComplexObject, Context, Object, SimpleObject}; use common::{IndexerAddress, IpfsCid}; -use graphix_common_types as common; +use graphix_common_types::{self as common, ApiKeyPermissionLevel}; use graphix_store::models::{self, IntId}; use num_traits::cast::ToPrimitive; -use super::{ctx_data, ApiSchemaContext}; +use super::{ctx_data, ServerState}; #[derive(Clone, derive_more::From)] pub struct SubgraphDeployment { @@ -20,7 +20,7 @@ impl SubgraphDeployment { self.model.name.as_deref() } - pub async fn network(&self, ctx: &ApiSchemaContext) -> Result { + pub async fn network(&self, ctx: &ServerState) -> Result { let loader = &ctx.loader_network; loader @@ -34,7 +34,7 @@ impl SubgraphDeployment { #[Object] impl SubgraphDeployment { - /// IPFS CID of the subgraph deployment. + /// IPFS CID of the subgraph deployment manifest e.g. `Qm...`. #[graphql(name = "cid")] async fn graphql_cid(&self) -> IpfsCid { self.model.cid.clone() @@ -53,6 +53,28 @@ impl SubgraphDeployment { } } +pub struct ApiKey { + model: models::NewlyCreatedApiKey, +} + +#[Object] +impl ApiKey { + #[graphql(name = "apiKey")] + async fn graphql_api_key(&self) -> String { + self.model.api_key.clone() + } + + #[graphql(name = "permissionLevel")] + async fn graphql_permission_level(&self) -> ApiKeyPermissionLevel { + self.model.permission_level.clone() + } + + #[graphql(name = "notes")] + async fn graphql_notes(&self) -> Option { + self.model.notes.clone() + } +} + /// A network where subgraph deployments are indexed. #[derive(derive_more::From)] pub struct Network { @@ -102,7 +124,7 @@ impl Indexer { pub async fn graph_node_version( &self, - ctx: &ApiSchemaContext, + ctx: &ServerState, ) -> Result, String> { let loader = &ctx.loader_graph_node_collected_version; @@ -224,7 +246,7 @@ impl Block { self.model.hash.clone().into() } - pub async fn network(&self, ctx: &ApiSchemaContext) -> Result { + pub async fn network(&self, ctx: &ServerState) -> Result { let loader = &ctx.loader_network; loader @@ -301,7 +323,7 @@ impl ProofOfIndexing { self.model.poi.clone().into() } - pub async fn deployment(&self, ctx: &ApiSchemaContext) -> Result { + pub async fn deployment(&self, ctx: &ServerState) -> Result { let loader = &ctx.loader_subgraph_deployment; loader @@ -312,7 +334,7 @@ impl ProofOfIndexing { .map(Into::into) } - pub async fn block(&self, ctx: &ApiSchemaContext) -> Result { + pub async fn block(&self, ctx: &ServerState) -> Result { let loader = &ctx.loader_block; loader @@ -323,7 +345,7 @@ impl ProofOfIndexing { .map(Into::into) } - pub async fn indexer(&self, ctx: &ApiSchemaContext) -> Result { + pub async fn indexer(&self, ctx: &ServerState) -> Result { let loader = &ctx.loader_indexer; loader diff --git a/crates/graphix_lib/src/graphql_api/mod.rs b/crates/graphix_lib/src/graphql_api/mod.rs index a846a7a..6d89a6f 100644 --- a/crates/graphix_lib/src/graphql_api/mod.rs +++ b/crates/graphix_lib/src/graphql_api/mod.rs @@ -1,18 +1,38 @@ pub mod api_types; -mod server; +mod mutation_root; +mod query_root; +use std::str::FromStr; +use std::sync::Arc; use std::time::Duration; use async_graphql::dataloader::DataLoader; +use async_graphql::http::GraphiQLSource; use async_graphql::{Context, EmptySubscription, Schema, SchemaBuilder}; +use async_graphql_axum::GraphQL; +use axum::extract::State; +use axum::http::header::AUTHORIZATION; +use axum::http::StatusCode; +use axum::Json; +use graphix_store::models::ApiKey; use graphix_store::{Store, StoreLoader}; +use tower_service::Service; -use self::server::{MutationRoot, QueryRoot}; +use self::mutation_root::MutationRoot; +use self::query_root::QueryRoot; use crate::config::Config; +use crate::GRAPHIX_VERSION; pub type ApiSchema = Schema; -pub struct ApiSchemaContext { +#[derive(derive_more::Deref)] +pub struct RequestState { + api_key: Option, + #[deref] + data: Arc, +} + +pub struct ServerState { pub store: Store, pub config: Config, pub loader_poi: DataLoader>, @@ -26,7 +46,7 @@ pub struct ApiSchemaContext { pub loader_subgraph_deployment: DataLoader>, } -impl ApiSchemaContext { +impl ServerState { pub fn new(store: Store, config: Config) -> Self { // The default delay is 1ms, but we're happy to wait a bit longer to reduce load on the // database. @@ -65,11 +85,69 @@ pub fn api_schema_builder() -> SchemaBuilder ApiSchema { - api_schema_builder().data(ctx).finish() +pub fn ctx_data<'a>(ctx: &'a Context) -> &'a RequestState { + ctx.data::() + .expect("Failed to get API context") } -pub fn ctx_data<'a>(ctx: &'a Context) -> &'a ApiSchemaContext { - ctx.data::() - .expect("Failed to get API context") +pub async fn axum_router(config: Config) -> anyhow::Result> { + use axum::routing::get; + + let store = Store::new(config.database_url.as_str()).await?; + let server_state = ServerState::new(store.clone(), config.clone()); + + Ok(axum::Router::new() + .route( + "/", + get(|| async { + format!( + "Welcome to Graphix v{}. Go to `/graphql` to use the playground.", + GRAPHIX_VERSION + ) + }), + ) + .route("/graphql", get(graphiql_route).post(graphql_handler)) + .with_state(Arc::new(server_state))) +} + +async fn graphql_handler( + State(state): State>, + request: axum::extract::Request, +) -> Result)> { + let api_key = match request.headers().get(AUTHORIZATION) { + None => None, + Some(value) => { + let header_s = value.to_str().map_err(api_key_error)?; + let api_key = ApiKey::from_str(header_s).map_err(api_key_error)?; + + Some(api_key) + } + }; + + let api_schema = api_schema_builder() + .data(RequestState { + api_key, + data: state.clone(), + }) + .finish(); + + let mut service = GraphQL::new(api_schema); + Ok(service + .call(request) + .await + .map_err(|_| api_key_error("Internal server error"))?) +} + +fn api_key_error(err: impl ToString) -> (StatusCode, Json) { + ( + StatusCode::UNAUTHORIZED, + Json(serde_json::json!({ + "message": "Invalid API key", + "error": err.to_string(), + })), + ) +} + +async fn graphiql_route() -> impl axum::response::IntoResponse { + axum::response::Html(GraphiQLSource::build().endpoint("/graphql").finish()) } diff --git a/crates/graphix_lib/src/graphql_api/mutation_root.rs b/crates/graphix_lib/src/graphql_api/mutation_root.rs new file mode 100644 index 0000000..0bcd1c1 --- /dev/null +++ b/crates/graphix_lib/src/graphql_api/mutation_root.rs @@ -0,0 +1,171 @@ +use async_graphql::{Context, Object, Result}; +use graphix_common_types::*; +use graphix_store::models::{DivergenceInvestigationRequest, NewlyCreatedApiKey}; + +use super::ctx_data; + +pub struct MutationRoot; + +#[Object] +impl MutationRoot { + /// Launches a divergence investigation, which is a process of comparing + /// two or more PoIs (up to four) and running a binary search to find the first + /// diverging block. + async fn launch_divergence_investigation( + &self, + ctx: &Context<'_>, + #[graphql( + validator(min_items = 2, max_items = 4), + desc = "A list of PoI hashes that should be investigated for divergence. If this list contains more than two PoIs, a new bisection run will be performed for each unordered pair of PoIs." + )] + pois: Vec, + #[graphql( + default = true, + desc = "Indicates whether to collect `graph-node`'s block cache contents during bisection runs to include in the report." + )] + query_block_caches: bool, + #[graphql( + default = true, + desc = "Indicates whether to collect `graph-node`'s ETH call cache contents during bisection runs to include in the report." + )] + query_eth_call_caches: bool, + #[graphql( + default = true, + desc = "Indicates whether to collect `graph-node`'s entity changes during bisection runs to include in the report." + )] + query_entity_changes: bool, + ) -> Result { + let ctx_data = ctx_data(ctx); + let store = &ctx_data.store; + + let req = DivergenceInvestigationRequest { + pois, + query_block_caches, + query_eth_call_caches, + query_entity_changes, + }; + let request_serialized = serde_json::to_value(req).unwrap(); + let uuid = store + .create_divergence_investigation_request(request_serialized) + .await?; + + let report = DivergenceInvestigationReport { + uuid: uuid.clone(), + status: DivergenceInvestigationStatus::Pending, + bisection_runs: vec![], + error: None, + }; + + Ok(report) + } + + /// Create a new API key with the given permission level. You'll need to + /// authenticate with another API key with the `admin` permission level to + /// do this. + async fn create_api_key( + &self, + ctx: &Context<'_>, + #[graphql(desc = "Permission level of the API key. Use `admin` for full access.")] + permission_level: ApiKeyPermissionLevel, + #[graphql( + default, + desc = "Not-encrypted notes to store in the database alongside the API key, to be used for debugging or identification purposes." + )] + notes: Option, + ) -> Result { + // In order to create an API key with a certain permission level, you + // need to have that permission level yourself. + require_permission_level(ctx, permission_level).await?; + + let ctx_data = ctx_data(ctx); + + let api_key = ctx_data + .store + .create_api_key(notes.as_deref(), permission_level) + .await?; + + Ok(api_key) + } + + async fn delete_api_key(&self, ctx: &Context<'_>, api_key: String) -> Result { + let ctx_data = ctx_data(ctx); + + ctx_data.store.delete_api_key(&api_key).await?; + + Ok(true) + } + + async fn modify_api_key( + &self, + ctx: &Context<'_>, + api_key: String, + #[graphql( + desc = "Not-encrypted notes to store in the database alongside the API key, to be used for debugging or identification purposes." + )] + notes: Option, + permission_level: ApiKeyPermissionLevel, + ) -> Result { + require_permission_level(ctx, permission_level).await?; + + let ctx_data = ctx_data(ctx); + + ctx_data + .store + .modify_api_key(&api_key, notes.as_deref(), permission_level) + .await?; + + Ok(true) + } + + async fn set_deployment_name( + &self, + ctx: &Context<'_>, + deployment_ipfs_cid: String, + name: String, + ) -> Result { + let ctx_data = ctx_data(ctx); + let store = &ctx_data.store; + + store + .set_deployment_name(&deployment_ipfs_cid, &name) + .await?; + + Ok(Deployment { + id: deployment_ipfs_cid, + }) + } + + /// Completely deletes a network and all related data (PoIs, indexers, subgraphs, etc.). + async fn delete_network(&self, ctx: &Context<'_>, network: String) -> Result { + let ctx_data = ctx_data(ctx); + ctx_data.store.delete_network(&network).await?; + + Ok(network) + } +} + +async fn require_permission_level( + ctx: &Context<'_>, + required_permission_level: ApiKeyPermissionLevel, +) -> Result<()> { + let ctx_data = ctx_data(ctx); + let api_key = ctx_data + .api_key + .as_ref() + .ok_or_else(|| anyhow::anyhow!("No API key provided"))?; + + let Some(actual_permission_level) = ctx_data.store.permission_level(&api_key).await? else { + return Err(anyhow::anyhow!("No permission level for API key").into()); + }; + + if actual_permission_level < required_permission_level { + return Err(anyhow::anyhow!( + "Insufficient permission level for API key: expected {:?}, got {:?}", + required_permission_level, + actual_permission_level + ) + .into()); + } + + Ok(()) +} diff --git a/crates/graphix_lib/src/graphql_api/server.rs b/crates/graphix_lib/src/graphql_api/query_root.rs similarity index 76% rename from crates/graphix_lib/src/graphql_api/server.rs rename to crates/graphix_lib/src/graphql_api/query_root.rs index 896a067..56cb04e 100644 --- a/crates/graphix_lib/src/graphql_api/server.rs +++ b/crates/graphix_lib/src/graphql_api/query_root.rs @@ -4,7 +4,7 @@ use anyhow::Context as _; use async_graphql::{Context, Object, Result}; use futures::future::try_join_all; use graphix_common_types::*; -use graphix_store::models::DivergenceInvestigationRequest; +use graphix_store::models::ApiKeyPublicMetadata; use uuid::Uuid; use super::{api_types, ctx_data}; @@ -130,6 +130,13 @@ impl QueryRoot { Ok(pois.into_iter().map(Into::into).collect()) } + async fn api_keys(&self, ctx: &Context<'_>) -> Result> { + let ctx_data = ctx_data(ctx); + let api_keys = ctx_data.store.api_keys().await?; + + Ok(api_keys) + } + async fn poi_agreement_ratios( &self, ctx: &Context<'_>, @@ -272,85 +279,3 @@ async fn live_pois( Ok(pois.into_iter().map(Into::into).collect()) } - -pub struct MutationRoot; - -#[Object] -impl MutationRoot { - /// Launches a divergence investigation, which is a process of comparing - /// two or more PoIs (up to four) and running a binary search to find the first - /// diverging block. - async fn launch_divergence_investigation( - &self, - ctx: &Context<'_>, - #[graphql( - validator(min_items = 2, max_items = 4), - desc = "A list of PoI hashes that should be investigated for divergence. If this list contains more than two PoIs, a new bisection run will be performed for each unordered pair of PoIs." - )] - pois: Vec, - #[graphql( - default = true, - desc = "Indicates whether to collect `graph-node`'s block cache contents during bisection runs to include in the report." - )] - query_block_caches: bool, - #[graphql( - default = true, - desc = "Indicates whether to collect `graph-node`'s eth call cache contents during bisection runs to include in the report." - )] - query_eth_call_caches: bool, - #[graphql( - default = true, - desc = "Indicates whether to collect `graph-node`'s entity changes during bisection runs to include in the report." - )] - query_entity_changes: bool, - ) -> Result { - let ctx_data = ctx_data(ctx); - let store = &ctx_data.store; - - let req = DivergenceInvestigationRequest { - pois, - query_block_caches, - query_eth_call_caches, - query_entity_changes, - }; - let request_serialized = serde_json::to_value(req).unwrap(); - let uuid = store - .create_divergence_investigation_request(request_serialized) - .await?; - - let report = DivergenceInvestigationReport { - uuid: uuid.clone(), - status: DivergenceInvestigationStatus::Pending, - bisection_runs: vec![], - error: None, - }; - - Ok(report) - } - - async fn set_deployment_name( - &self, - ctx: &Context<'_>, - deployment_ipfs_cid: String, - name: String, - ) -> Result { - let ctx_data = ctx_data(ctx); - let store = &ctx_data.store; - - store - .set_deployment_name(&deployment_ipfs_cid, &name) - .await?; - - Ok(Deployment { - id: deployment_ipfs_cid, - }) - } - - /// Completely deletes a network and all related data (PoIs, indexers, subgraphs, etc.). - async fn delete_network(&self, ctx: &Context<'_>, network: String) -> Result { - let ctx_data = ctx_data(ctx); - ctx_data.store.delete_network(&network).await?; - - Ok(network) - } -} diff --git a/crates/store/Cargo.toml b/crates/store/Cargo.toml index 44c4acc..e098f4e 100644 --- a/crates/store/Cargo.toml +++ b/crates/store/Cargo.toml @@ -5,7 +5,6 @@ edition = "2021" [dependencies] anyhow = { workspace = true } -async-trait = { workspace = true } async-graphql = { workspace = true, features = ["dataloader"] } bigdecimal = { workspace = true, features = ["serde"] } chrono = { workspace = true, features = ["serde"] } @@ -17,10 +16,13 @@ graphix_indexer_client = { path = "../indexer_client" } hex = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } +sha2 = { workspace = true } +strum = { workspace = true } tracing = { workspace = true } uuid = { workspace = true, features = ["v4"] } [dev-dependencies] +derive_more = { workspace = true } graphix_common_types = { path = "../common_types" } graphix_lib = { path = "../graphix_lib" } testcontainers = { workspace = true } diff --git a/crates/store/migrations/2023-03-30-000000_initial_schema/up.sql b/crates/store/migrations/2023-03-30-000000_initial_schema/up.sql index 97148ad..123819c 100644 --- a/crates/store/migrations/2023-03-30-000000_initial_schema/up.sql +++ b/crates/store/migrations/2023-03-30-000000_initial_schema/up.sql @@ -137,3 +137,11 @@ CREATE TABLE failed_queries ( ); CREATE INDEX ON failed_queries (indexer_id, query_name); + +-- API key management. +CREATE TABLE graphix_api_tokens ( + public_prefix TEXT PRIMARY KEY, + sha256_api_key_hash BYTEA NOT NULL UNIQUE, + notes TEXT, + permission_level INTEGER NOT NULL +); diff --git a/crates/store/src/lib.rs b/crates/store/src/lib.rs index 52c624c..703a581 100644 --- a/crates/store/src/lib.rs +++ b/crates/store/src/lib.rs @@ -3,20 +3,23 @@ mod diesel_queries; mod loader; +use anyhow::anyhow; use diesel_async::pooled_connection::deadpool::{Object, Pool}; use diesel_async::pooled_connection::AsyncDieselConnectionManager; use diesel_async::scoped_futures::ScopedFutureExt; use diesel_async::{AsyncConnection, AsyncPgConnection, RunQueryDsl}; -#[cfg(tests)] -pub use diesel_queries; -use graphix_common_types::{inputs, IndexerAddress, IpfsCid, PoiBytes}; -use models::{FailedQueryRow, NewIndexerNetworkSubgraphMetadata, SgDeployment}; +use graphix_common_types::{inputs, ApiKeyPermissionLevel, IndexerAddress, IpfsCid, PoiBytes}; +use models::{ + ApiKey, ApiKeyDbRow, ApiKeyPublicMetadata, FailedQueryRow, NewIndexerNetworkSubgraphMetadata, + NewlyCreatedApiKey, SgDeployment, +}; use uuid::Uuid; pub mod models; mod schema; use std::collections::HashMap; use std::fmt::Debug; +use std::str::FromStr; use std::sync::Arc; use anyhow::Error; @@ -37,6 +40,7 @@ pub struct Store { impl Debug for Store { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // It might contain sensitive data, so don't print it. f.debug_struct("Store").finish() } } @@ -54,18 +58,17 @@ impl Store { store.run_migrations().await?; + if store.api_keys().await?.is_empty() { + info!("No API keys found in database, creating master API key"); + store.create_master_api_key().await?; + } + Ok(store) } async fn run_migrations(&self) -> anyhow::Result<()> { let mut conn = self.pool.get().await?; - // Get a lock for running migrations. Blocks until we get the lock. - // We need this because different Graphix instances may attempt - // to run migrations concurrently (that's a big no-no). - diesel::sql_query("select pg_advisory_lock(1)") - .execute(&mut conn) - .await?; info!("Run database migrations"); Self::MIGRATIONS @@ -73,10 +76,24 @@ impl Store { .await .map_err(|e| anyhow::anyhow!(e))?; - // Release the migration lock. - diesel::sql_query("select pg_advisory_unlock(1)") - .execute(&mut conn) + Ok(()) + } + + async fn create_master_api_key(&self) -> anyhow::Result<()> { + let api_key = self + .create_api_key(None, ApiKeyPermissionLevel::Admin) .await?; + + let description = format!("Master API key created during database initialization. Use it to create a new private API key and then delete it for security reasons. `{}`", api_key.api_key.to_string()); + self.modify_api_key( + &api_key.api_key, + Some(&description), + ApiKeyPermissionLevel::Admin, + ) + .await?; + + info!(api_key = ?api_key.api_key, "Created master API key"); + Ok(()) } @@ -420,6 +437,93 @@ impl Store { Ok(indexer_id) } + pub async fn create_api_key( + &self, + notes: Option<&str>, + permission_level: ApiKeyPermissionLevel, + ) -> anyhow::Result { + use schema::graphix_api_tokens; + + let api_key = ApiKey::generate(); + let stored_api_key = ApiKeyDbRow { + public_prefix: api_key.public_part_as_string(), + sha256_api_key_hash: api_key.hash(), + notes: notes.map(|s| s.to_string()), + permission_level, + }; + + diesel::insert_into(graphix_api_tokens::table) + .values(&[stored_api_key]) + .execute(&mut self.conn().await?) + .await?; + + Ok(NewlyCreatedApiKey { + api_key: api_key.to_string(), + notes: notes.map(|s| s.to_string()), + permission_level, + }) + } + + pub async fn modify_api_key( + &self, + api_key_s: &str, + notes: Option<&str>, + permission_level: ApiKeyPermissionLevel, + ) -> anyhow::Result<()> { + use schema::graphix_api_tokens; + + let api_key = ApiKey::from_str(api_key_s).map_err(|e| anyhow!("invalid api key: {}", e))?; + + diesel::update(graphix_api_tokens::table) + .filter(graphix_api_tokens::sha256_api_key_hash.eq(api_key.hash())) + .set(( + graphix_api_tokens::notes.eq(notes), + graphix_api_tokens::permission_level.eq(permission_level), + )) + .execute(&mut self.conn().await?) + .await?; + + Ok(()) + } + + pub async fn delete_api_key(&self, api_key_s: &str) -> anyhow::Result<()> { + use schema::graphix_api_tokens; + + let api_key = ApiKey::from_str(api_key_s).map_err(|e| anyhow!("invalid api key: {}", e))?; + + diesel::delete(graphix_api_tokens::table) + .filter(graphix_api_tokens::sha256_api_key_hash.eq(api_key.hash())) + .execute(&mut self.conn().await?) + .await?; + + Ok(()) + } + + pub async fn api_keys(&self) -> anyhow::Result> { + use schema::graphix_api_tokens; + + Ok(graphix_api_tokens::table + .load::(&mut self.conn().await?) + .await? + .into_iter() + .map(ApiKeyPublicMetadata::from) + .collect()) + } + + pub async fn permission_level( + &self, + api_key: &ApiKey, + ) -> anyhow::Result> { + use schema::graphix_api_tokens; + + Ok(graphix_api_tokens::table + .select(graphix_api_tokens::permission_level) + .filter(graphix_api_tokens::sha256_api_key_hash.eq(api_key.hash())) + .get_result(&mut self.conn().await?) + .await + .optional()?) + } + pub async fn write_graph_node_versions( &self, versions: HashMap< diff --git a/crates/store/src/loader.rs b/crates/store/src/loader.rs index be2f9f1..b62b9f2 100644 --- a/crates/store/src/loader.rs +++ b/crates/store/src/loader.rs @@ -1,7 +1,6 @@ use std::collections::HashMap; use std::marker::PhantomData; -use async_trait::async_trait; use diesel::prelude::*; use diesel_async::RunQueryDsl; @@ -22,7 +21,6 @@ impl StoreLoader { } } -#[async_trait] impl async_graphql::dataloader::Loader for StoreLoader { type Value = models::Block; type Error = String; @@ -41,7 +39,6 @@ impl async_graphql::dataloader::Loader for StoreLoader } } -#[async_trait] impl async_graphql::dataloader::Loader for StoreLoader { type Value = models::Poi; type Error = String; @@ -60,7 +57,6 @@ impl async_graphql::dataloader::Loader for StoreLoader { } } -#[async_trait] impl async_graphql::dataloader::Loader for StoreLoader { type Value = models::SgDeployment; type Error = String; @@ -87,7 +83,6 @@ impl async_graphql::dataloader::Loader for StoreLoader for StoreLoader { type Value = models::Network; type Error = String; @@ -110,7 +105,6 @@ impl async_graphql::dataloader::Loader for StoreLoader { } } -#[async_trait] impl async_graphql::dataloader::Loader for StoreLoader { type Value = models::Indexer; type Error = String; @@ -129,7 +123,6 @@ impl async_graphql::dataloader::Loader for StoreLoader { } } -#[async_trait] impl async_graphql::dataloader::Loader for StoreLoader { type Value = models::GraphNodeCollectedVersion; type Error = String; @@ -148,7 +141,6 @@ impl async_graphql::dataloader::Loader for StoreLoader for StoreLoader { diff --git a/crates/store/src/models.rs b/crates/store/src/models.rs index 2ff078d..382d7cf 100644 --- a/crates/store/src/models.rs +++ b/crates/store/src/models.rs @@ -8,10 +8,12 @@ use diesel::deserialize::FromSql; use diesel::pg::Pg; use diesel::sql_types::Jsonb; use diesel::{AsChangeset, AsExpression, FromSqlRow, Insertable, Queryable, Selectable}; -use graphix_common_types as types; +use graphix_common_types::{self as types, ApiKeyPermissionLevel}; use graphix_indexer_client::IndexerId; use serde::{Deserialize, Serialize}; +use sha2::Digest; use types::{BlockHash, IndexerAddress, IpfsCid, PoiBytes}; +use uuid::Uuid; use super::schema::*; @@ -127,6 +129,87 @@ impl IndexerId for Indexer { } } +#[derive(Debug, Clone, Insertable, Queryable, Selectable)] +#[diesel(table_name = graphix_api_tokens)] +pub struct ApiKeyDbRow { + pub public_prefix: String, + pub sha256_api_key_hash: Vec, + pub notes: Option, + pub permission_level: ApiKeyPermissionLevel, +} + +#[derive(Debug, Clone, SimpleObject)] +pub struct ApiKeyPublicMetadata { + pub public_prefix: String, + pub notes: Option, + pub permission_level: ApiKeyPermissionLevel, +} + +impl From for ApiKeyPublicMetadata { + fn from(sak: ApiKeyDbRow) -> Self { + Self { + public_prefix: sak.public_prefix, + notes: sak.notes, + permission_level: sak.permission_level, + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ApiKey { + public_part: Uuid, + private_part: Uuid, +} + +impl ApiKey { + pub fn generate() -> Self { + Self { + public_part: Uuid::new_v4(), + private_part: Uuid::new_v4(), + } + } + + pub fn public_part_as_string(&self) -> String { + self.public_part.as_simple().to_string() + } + + pub fn hash(&self) -> Vec { + sha2::Sha256::digest(self.to_string().as_bytes()).to_vec() + } +} + +impl std::str::FromStr for ApiKey { + type Err = String; + + fn from_str(s: &str) -> Result { + let parts: Vec<&str> = s.split('-').collect(); + let parts: [&str; 3] = parts.try_into().map_err(|_| "invalid api key format")?; + + if parts[0] != "graphix" { + return Err("invalid api key format".to_string()); + } + + let public_part = Uuid::try_parse(parts[1]).map_err(|e| e.to_string())?; + let private_part = Uuid::try_parse(parts[2]).map_err(|e| e.to_string())?; + + Ok(Self { + public_part, + private_part, + }) + } +} + +impl std::fmt::Display for ApiKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "graphix-{}-{}", + self.public_part.as_simple(), + self.private_part.as_simple() + ) + } +} + #[derive(Debug, Clone, Queryable, Selectable, Serialize, PartialEq, Eq)] #[diesel(table_name = networks)] pub struct Network { @@ -182,6 +265,13 @@ pub struct NewIndexer { pub name: Option, } +#[derive(Debug, Clone, async_graphql::SimpleObject)] +pub struct NewlyCreatedApiKey { + pub api_key: String, + pub notes: Option, + pub permission_level: ApiKeyPermissionLevel, +} + #[derive(Debug, Clone, Queryable, Serialize)] pub struct SgDeployment { pub id: IntId, @@ -255,3 +345,18 @@ impl FromSql for DivergingBlock { // } // } //} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use super::*; + + #[test] + fn api_key_from_str() { + let api_key = ApiKey::generate(); + let parsed = ApiKey::from_str(&format!("{}", api_key)).unwrap(); + + assert_eq!(api_key, parsed); + } +} diff --git a/crates/store/src/schema.rs b/crates/store/src/schema.rs index 2df7b2c..4d63d74 100644 --- a/crates/store/src/schema.rs +++ b/crates/store/src/schema.rs @@ -38,6 +38,15 @@ diesel::table! { } } +diesel::table! { + graphix_api_tokens (public_prefix) { + public_prefix -> Text, + sha256_api_key_hash -> Bytea, + notes -> Nullable, + permission_level -> Int4, + } +} + diesel::table! { indexer_network_subgraph_metadata (id) { id -> Int4, @@ -150,6 +159,7 @@ diesel::allow_tables_to_appear_in_same_query!( divergence_investigation_reports, failed_queries, graph_node_collected_versions, + graphix_api_tokens, indexer_network_subgraph_metadata, indexers, live_pois, diff --git a/crates/store/tests/common/mod.rs b/crates/store/tests/common/mod.rs index b69db0b..26bf520 100644 --- a/crates/store/tests/common/mod.rs +++ b/crates/store/tests/common/mod.rs @@ -1,25 +1,27 @@ -use std::ops::Deref; - use graphix_store::Store; -use testcontainers::clients::Cli; -use testcontainers::Container; +use testcontainers::runners::AsyncRunner; +use testcontainers::ContainerAsync; +use testcontainers_modules::postgres::Postgres; + +const POSTGRES_PORT: u16 = 5432; /// A wrapper around a [`Store`] that is backed by a containerized Postgres /// database. -pub struct EmptyStoreForTesting<'a> { - _container: Container<'a, testcontainers_modules::postgres::Postgres>, +#[derive(derive_more::Deref)] +pub struct EmptyStoreForTesting { + #[deref] store: Store, + _container: ContainerAsync, } -impl<'a> EmptyStoreForTesting<'a> { - pub async fn new(docker_client: &'a Cli) -> anyhow::Result> { - use testcontainers_modules::postgres::Postgres; - - let container = docker_client.run(Postgres::default()); +impl EmptyStoreForTesting { + pub async fn new() -> anyhow::Result { + let container = Postgres::default().start().await?; let connection_string = &format!( "postgres://postgres:postgres@127.0.0.1:{}/postgres", - container.get_host_port_ipv4(5432) + container.get_host_port_ipv4(POSTGRES_PORT).await? ); + let store = Store::new(connection_string).await?; Ok(Self { _container: container, @@ -27,11 +29,3 @@ impl<'a> EmptyStoreForTesting<'a> { }) } } - -impl<'a> Deref for EmptyStoreForTesting<'a> { - type Target = Store; - - fn deref(&self) -> &Self::Target { - &self.store - } -} diff --git a/crates/store/tests/tests.rs b/crates/store/tests/tests.rs index df2466b..45725e6 100644 --- a/crates/store/tests/tests.rs +++ b/crates/store/tests/tests.rs @@ -2,14 +2,12 @@ mod common; use graphix_common_types::inputs::SgDeploymentsQuery; use graphix_store::models::{Network, NewNetwork}; -use testcontainers::clients::Cli; use crate::common::EmptyStoreForTesting; #[tokio::test] async fn empty_store_has_no_deployments() { - let docker_cli = Cli::default(); - let store = EmptyStoreForTesting::new(&docker_cli).await.unwrap(); + let store = EmptyStoreForTesting::new().await.unwrap(); let initial_deployments = store .sg_deployments(SgDeploymentsQuery::default()) .await @@ -19,8 +17,7 @@ async fn empty_store_has_no_deployments() { #[tokio::test] async fn create_then_delete_network() { - let docker_cli = Cli::default(); - let store = EmptyStoreForTesting::new(&docker_cli).await.unwrap(); + let store = EmptyStoreForTesting::new().await.unwrap(); assert_eq!(store.networks().await.unwrap(), vec![]); @@ -49,8 +46,7 @@ async fn create_then_delete_network() { #[tokio::test] #[should_panic] // FIXME async fn deployments_with_name() { - let docker_cli = Cli::default(); - let store = EmptyStoreForTesting::new(&docker_cli).await.unwrap(); + let store = EmptyStoreForTesting::new().await.unwrap(); let ipfs_cid1 = "QmNY7gDNXHECV8SXoEY7hbfg4BX1aDMxTBDiFuG4huaSGA"; let ipfs_cid2 = "QmYzsCjrVwwXtdsNm3PZVNziLGmb9o513GUzkq5wwhgXDT"; @@ -80,8 +76,7 @@ async fn deployments_with_name() { #[tokio::test] async fn create_divergence_investigation_request() { - let docker_cli = Cli::default(); - let store = EmptyStoreForTesting::new(&docker_cli).await.unwrap(); + let store = EmptyStoreForTesting::new().await.unwrap(); let uuid = store .create_divergence_investigation_request(serde_json::json!({})) diff --git a/ops/compose/dependencies.yml b/ops/compose/dependencies.yml index 64d39fb..ef9a932 100644 --- a/ops/compose/dependencies.yml +++ b/ops/compose/dependencies.yml @@ -2,7 +2,7 @@ version: "3" services: grafana: - image: grafana/grafana-oss + image: grafana/grafana-oss:9.3.16 restart: unless-stopped # https://community.grafana.com/t/new-docker-install-with-persistent-storage-permission-problem/10896/16 user: ":" @@ -12,8 +12,6 @@ services: ports: - "3000:3000" environment: - # Plugins: - # - https://github.com/fifemon/graphql-datasource for GraphQL data sources. - GF_INSTALL_PLUGINS=fifemon-graphql-datasource,yesoreyeram-infinity-datasource volumes: - ./grafana/config/:/etc/grafana/ diff --git a/ops/compose/grafana/data/alerting/1/__default__.tmpl b/ops/compose/grafana/data/alerting/1/__default__.tmpl deleted file mode 100644 index b8633d1..0000000 --- a/ops/compose/grafana/data/alerting/1/__default__.tmpl +++ /dev/null @@ -1,53 +0,0 @@ - -{{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ if gt (.Alerts.Resolved | len) 0 }}, RESOLVED:{{ .Alerts.Resolved | len }}{{ end }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }} {{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ with .CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{ end }}{{ end }} - -{{ define "__text_values_list" }}{{ if len .Values }}{{ $first := true }}{{ range $refID, $value := .Values -}} -{{ if $first }}{{ $first = false }}{{ else }}, {{ end }}{{ $refID }}={{ $value }}{{ end -}} -{{ else }}[no value]{{ end }}{{ end }} - -{{ define "__text_alert_list" }}{{ range . }} -Value: {{ template "__text_values_list" . }} -Labels: -{{ range .Labels.SortedPairs }} - {{ .Name }} = {{ .Value }} -{{ end }}Annotations: -{{ range .Annotations.SortedPairs }} - {{ .Name }} = {{ .Value }} -{{ end }}{{ if gt (len .GeneratorURL) 0 }}Source: {{ .GeneratorURL }} -{{ end }}{{ if gt (len .SilenceURL) 0 }}Silence: {{ .SilenceURL }} -{{ end }}{{ if gt (len .DashboardURL) 0 }}Dashboard: {{ .DashboardURL }} -{{ end }}{{ if gt (len .PanelURL) 0 }}Panel: {{ .PanelURL }} -{{ end }}{{ end }}{{ end }} - -{{ define "default.title" }}{{ template "__subject" . }}{{ end }} - -{{ define "default.message" }}{{ if gt (len .Alerts.Firing) 0 }}**Firing** -{{ template "__text_alert_list" .Alerts.Firing }}{{ if gt (len .Alerts.Resolved) 0 }} - -{{ end }}{{ end }}{{ if gt (len .Alerts.Resolved) 0 }}**Resolved** -{{ template "__text_alert_list" .Alerts.Resolved }}{{ end }}{{ end }} - - -{{ define "__teams_text_alert_list" }}{{ range . }} -Value: {{ template "__text_values_list" . }} -Labels: -{{ range .Labels.SortedPairs }} - {{ .Name }} = {{ .Value }} -{{ end }} -Annotations: -{{ range .Annotations.SortedPairs }} - {{ .Name }} = {{ .Value }} -{{ end }} -{{ if gt (len .GeneratorURL) 0 }}Source: [{{ .GeneratorURL }}]({{ .GeneratorURL }}) - -{{ end }}{{ if gt (len .SilenceURL) 0 }}Silence: [{{ .SilenceURL }}]({{ .SilenceURL }}) - -{{ end }}{{ if gt (len .DashboardURL) 0 }}Dashboard: [{{ .DashboardURL }}]({{ .DashboardURL }}) - -{{ end }}{{ if gt (len .PanelURL) 0 }}Panel: [{{ .PanelURL }}]({{ .PanelURL }}) - -{{ end }} -{{ end }}{{ end }} - - -{{ define "teams.default.message" }}{{ if gt (len .Alerts.Firing) 0 }}**Firing** -{{ template "__teams_text_alert_list" .Alerts.Firing }}{{ if gt (len .Alerts.Resolved) 0 }} - -{{ end }}{{ end }}{{ if gt (len .Alerts.Resolved) 0 }}**Resolved** -{{ template "__teams_text_alert_list" .Alerts.Resolved }}{{ end }}{{ end }} diff --git a/ops/compose/grafana/data/grafana.db b/ops/compose/grafana/data/grafana.db index 767d861..d1fc6ce 100644 Binary files a/ops/compose/grafana/data/grafana.db and b/ops/compose/grafana/data/grafana.db differ diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 1c8cfba..d2bc0cc 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.75.0" +channel = "1.78.0" profile = "default"