diff --git a/.prettierignore b/.prettierignore index 45be9c1814..9ee4834b58 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,2 @@ target/ -*.schema.json -.vscode/ +.tailcall.schema.json \ No newline at end of file diff --git a/.prettierrc b/.prettierrc index 31560a2ef3..0903e25172 100644 --- a/.prettierrc +++ b/.prettierrc @@ -13,8 +13,7 @@ "inline-many-list.graphql", "test-grpc.graphql", "test-expr-success.graphql", - "omit-many.graphql", - "tests/graphql/auth.graphql" + "omit-many.graphql" ], "options": { "printWidth": 200 diff --git a/.vscode/settings.json b/.vscode/settings.json index 4df3a2d179..3b5a11bd25 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,15 +1,6 @@ { "rust-analyzer.linkedProjects": ["./Cargo.toml", "./cloudflare/Cargo.toml"], - "cSpell.words": [ - "hasher", - "Htpasswd", - "httpmock", - "indexmap", - "jwks", - "prost", - "Sfixed", - "thiserror" - ], + "cSpell.words": ["hasher", "thiserror", "indexmap", "prost", "Sfixed", "httpmock"], "files.watcherExclude": { "**/target": true }, diff --git a/Cargo.lock b/Cargo.lock index 64582e0394..aa10fa41d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,9 +40,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", "once_cell", @@ -108,30 +108,30 @@ checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -188,12 +188,12 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d37875bd9915b7d67c2f117ea2c30a0989874d0b2cb694fe25403c85763c0c9e" +checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" dependencies = [ "concurrent-queue", - "event-listener 3.1.0", + "event-listener 4.0.3", "event-listener-strategy", "futures-core", "pin-project-lite", @@ -201,30 +201,30 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc5ea910c42e5ab19012bab31f53cb4d63d54c3a27730f9a833a88efcf4bb52d" +checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" dependencies = [ - "async-lock 3.1.1", + "async-lock 3.3.0", "async-task", "concurrent-queue", "fastrand 2.0.1", - "futures-lite 2.0.1", + "futures-lite 2.2.0", "slab", ] [[package]] name = "async-global-executor" -version = "2.3.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel 1.9.0", + "async-channel 2.1.1", "async-executor", - "async-io 1.13.0", - "async-lock 2.8.0", + "async-io 2.2.2", + "async-lock 3.3.0", "blocking", - "futures-lite 1.13.0", + "futures-lite 2.2.0", "once_cell", ] @@ -278,7 +278,7 @@ dependencies = [ "proc-macro2", "quote", "strum", - "syn 2.0.46", + "syn 2.0.48", "thiserror", ] @@ -328,22 +328,21 @@ dependencies = [ [[package]] name = "async-io" -version = "2.2.0" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ed9d5715c2d329bf1b4da8d60455b99b187f27ba726df2883799af9af60997" +checksum = "6afaa937395a620e33dc6a742c593c01aced20aa376ffb0f628121198578ccc7" dependencies = [ - "async-lock 3.1.1", + "async-lock 3.3.0", "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.0.1", + "futures-lite 2.2.0", "parking", - "polling 3.3.0", - "rustix 0.38.25", + "polling 3.3.2", + "rustix 0.38.30", "slab", "tracing", - "waker-fn", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -357,11 +356,11 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.1.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655b9c7fe787d3b25cc0f804a1a8401790f0c5bc395beb5a64dc77d8de079105" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" dependencies = [ - "event-listener 3.1.0", + "event-listener 4.0.3", "event-listener-strategy", "pin-project-lite", ] @@ -388,7 +387,7 @@ dependencies = [ "cfg-if", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.25", + "rustix 0.38.30", "windows-sys 0.48.0", ] @@ -398,13 +397,13 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" dependencies = [ - "async-io 2.2.0", + "async-io 2.2.2", "async-lock 2.8.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.25", + "rustix 0.38.30", "signal-hook-registry", "slab", "windows-sys 0.48.0", @@ -457,14 +456,14 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] name = "async-task" -version = "4.5.0" +version = "4.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4eb2cdb97421e01129ccb49169d8279ed21e829929144f4a22a6e54ac549ca1" +checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" @@ -474,7 +473,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -526,34 +525,21 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "basic-cookies" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb53b6b315f924c7f113b162e53b3901c05fc9966baf84d201dfcc7432a4bb38" +checksum = "67bd8fd42c16bdb08688243dc5f0cc117a3ca9efeeaba3a345a18a6159ad96f7" dependencies = [ "lalrpop", "lalrpop-util", "regex", ] -[[package]] -name = "bcrypt" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d1c9c15093eb224f0baa400f38fcd713fc1391a6f1c389d886beef146d60a3" -dependencies = [ - "base64 0.21.5", - "blowfish 0.9.1", - "getrandom", - "subtle", - "zeroize", -] - [[package]] name = "beef" version = "0.5.2" @@ -596,15 +582,6 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -620,37 +597,16 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ - "async-channel 2.1.0", - "async-lock 3.1.1", + "async-channel 2.1.1", + "async-lock 3.3.0", "async-task", "fastrand 2.0.1", "futures-io", - "futures-lite 2.0.1", + "futures-lite 2.2.0", "piper", "tracing", ] -[[package]] -name = "blowfish" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32fa6a061124e37baba002e496d203e23ba3d7b73750be82dbfbc92913048a5b" -dependencies = [ - "byteorder", - "cipher 0.2.5", - "opaque-debug", -] - -[[package]] -name = "blowfish" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" -dependencies = [ - "byteorder", - "cipher 0.4.4", -] - [[package]] name = "bumpalo" version = "3.14.0" @@ -663,12 +619,6 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "bytes" version = "1.5.0" @@ -695,9 +645,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff" +checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" dependencies = [ "serde", ] @@ -805,25 +755,6 @@ dependencies = [ "half", ] -[[package]] -name = "cipher" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" -dependencies = [ - "generic-array", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - [[package]] name = "clap" version = "4.4.18" @@ -855,7 +786,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -889,11 +820,10 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "colored" -version = "2.0.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" dependencies = [ - "is-terminal", "lazy_static", "windows-sys 0.48.0", ] @@ -910,18 +840,18 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" +checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" dependencies = [ "crossbeam-utils", ] [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -929,15 +859,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -954,7 +884,7 @@ dependencies = [ "clap", "criterion-plot", "is-terminal", - "itertools", + "itertools 0.10.5", "num-traits", "once_cell", "oorandom", @@ -975,51 +905,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", - "itertools", + "itertools 0.10.5", ] [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crossterm" @@ -1062,16 +983,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "crypto-mac" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4857fd85a0c34b3c3297875b747c1e02e06b6a0ea32dd892d8192b9ce0813ea6" -dependencies = [ - "generic-array", - "subtle", -] - [[package]] name = "darling" version = "0.20.3" @@ -1093,7 +1004,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -1104,14 +1015,14 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] name = "deranged" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] @@ -1125,7 +1036,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -1134,22 +1045,13 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", + "block-buffer", "crypto-common", ] @@ -1225,12 +1127,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1259,13 +1161,24 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "event-listener" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + [[package]] name = "event-listener-strategy" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" dependencies = [ - "event-listener 3.1.0", + "event-listener 4.0.3", "pin-project-lite", ] @@ -1313,9 +1226,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -1368,14 +1281,13 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3831c2651acb5177cbd83943f3d9c8912c5ad03c76afcc0e9511ba568ec5ebb" +checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" dependencies = [ "fastrand 2.0.1", "futures-core", "futures-io", - "memchr", "parking", "pin-project-lite", ] @@ -1388,7 +1300,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -1443,17 +1355,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi", - "wasm-bindgen", ] [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "glob" @@ -1475,9 +1385,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "b553656127a00601c8ae5590fcfdc118e4083a7924b6cf4ffc1ea4b99dc429d7" dependencies = [ "bytes", "fnv", @@ -1523,38 +1433,14 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.7", "allocator-api2", ] -[[package]] -name = "headers" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" -dependencies = [ - "base64 0.21.5", - "bytes", - "headers-core", - "http 0.2.11", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http 0.2.11", -] - [[package]] name = "heck" version = "0.4.1" @@ -1567,35 +1453,13 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" -[[package]] -name = "hmac" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" -dependencies = [ - "crypto-mac", - "digest 0.9.0", -] - [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.48.0", -] - -[[package]] -name = "htpasswd-verify" -version = "0.3.0" -source = "git+https://github.com/twistedfall/htpasswd-verify?rev=ff14703083cbd639f7d05622b398926f3e718d61#ff14703083cbd639f7d05622b398926f3e718d61" -dependencies = [ - "base64 0.21.5", - "bcrypt", - "md-5 0.10.6", - "pwhash", - "sha1", + "windows-sys 0.52.0", ] [[package]] @@ -1622,9 +1486,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http 0.2.11", @@ -1709,7 +1573,7 @@ dependencies = [ "async-object-pool", "async-std", "async-trait", - "base64 0.21.5", + "base64 0.21.7", "basic-cookies", "crossbeam-utils", "form_urlencoded", @@ -1735,9 +1599,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -1750,7 +1614,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.5", "tokio", "tower-service", "tracing", @@ -1766,7 +1630,7 @@ dependencies = [ "futures-util", "http 0.2.11", "hyper", - "rustls 0.21.9", + "rustls 0.21.10", "tokio", "tokio-rustls 0.24.1", ] @@ -1790,9 +1654,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1819,9 +1683,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1834,19 +1698,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown 0.14.2", + "hashbrown 0.14.3", "serde", ] -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - [[package]] name = "inquire" version = "0.6.2" @@ -1891,13 +1746,13 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" dependencies = [ "hermit-abi", - "rustix 0.38.25", - "windows-sys 0.48.0", + "rustix 0.38.30", + "windows-sys 0.52.0", ] [[package]] @@ -1909,11 +1764,20 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jni" @@ -1946,21 +1810,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "jsonwebtoken" -version = "9.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ea04a7c5c055c175f189b6dc6ba036fd62306b58c66c9f6389036c503a3f4" -dependencies = [ - "base64 0.21.5", - "js-sys", - "pem", - "ring", - "serde", - "serde_json", - "simple_asn1", -] - [[package]] name = "kv-log-macro" version = "1.0.7" @@ -1972,20 +1821,21 @@ dependencies = [ [[package]] name = "lalrpop" -version = "0.19.12" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1cbf952127589f2851ab2046af368fd20645491bb4b376f04b7f94d7a9837b" +checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8" dependencies = [ "ascii-canvas", "bit-set", "diff", "ena", "is-terminal", - "itertools", + "itertools 0.10.5", "lalrpop-util", "petgraph", + "pico-args", "regex", - "regex-syntax 0.6.29", + "regex-syntax 0.7.5", "string_cache", "term", "tiny-keccak", @@ -1994,9 +1844,9 @@ dependencies = [ [[package]] name = "lalrpop-util" -version = "0.19.12" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3c48237b9604c5a4702de6b824e02006c3214327564636aef27c1028a8fa0ed" +checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d" dependencies = [ "regex", ] @@ -2015,9 +1865,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libmimalloc-sys" @@ -2054,9 +1904,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "lock_api" @@ -2097,7 +1947,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax 0.6.29", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -2124,7 +1974,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2994eeba8ed550fd9b47a0b38f0242bc3344e496483c6180b69139cc2fa5d1d7" dependencies = [ - "hashbrown 0.14.2", + "hashbrown 0.14.3", ] [[package]] @@ -2142,41 +1992,11 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9376a4f0340565ad675d11fc1419227faf5f60cd7ac9cb2e7185a471f30af833" -[[package]] -name = "md-5" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest 0.10.7", -] - [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "miette" @@ -2198,7 +2018,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -2252,9 +2072,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "log", @@ -2335,27 +2155,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "num-bigint" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.17" @@ -2386,9 +2185,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -2405,12 +2204,6 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - [[package]] name = "openssl-probe" version = "0.1.5" @@ -2419,9 +2212,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "ordered-float" -version = "2.10.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" dependencies = [ "num-traits", ] @@ -2464,27 +2257,17 @@ dependencies = [ "regex", ] -[[package]] -name = "pem" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" -dependencies = [ - "base64 0.21.5", - "serde", -] - [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" +checksum = "1f200d8d83c44a45b21764d1916299752ca035d15ecd46faca3e9a2a2bf6ad06" dependencies = [ "memchr", "thiserror", @@ -2493,9 +2276,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" +checksum = "bcd6ab1236bbdb3a49027e920e693192ebfe8913f6d60e294de57463a493cfde" dependencies = [ "pest", "pest_generator", @@ -2503,26 +2286,26 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" +checksum = "2a31940305ffc96863a735bef7c7994a00b325a7138fdbc5bda0f1a0476d3275" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] name = "pest_meta" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" +checksum = "a7ff62f5259e53b78d1af898941cdcdccfae7385cf7d793a6e55de5d05bb4b7d" dependencies = [ "once_cell", "pest", - "sha2 0.10.8", + "sha2", ] [[package]] @@ -2582,6 +2365,12 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pin-project" version = "1.1.3" @@ -2599,7 +2388,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -2671,16 +2460,16 @@ dependencies = [ [[package]] name = "polling" -version = "3.3.0" +version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53b6af1f60f36f8c2ac2aad5459d75a5a9b4be1e8cdd40264f315d78193e531" +checksum = "545c980a3880efd47b2e262f6a4bb6daad6555cf3367aa9c4e52895f69537a41" dependencies = [ "cfg-if", "concurrent-queue", "pin-project-lite", - "rustix 0.38.25", + "rustix 0.38.30", "tracing", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2689,12 +2478,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - [[package]] name = "precomputed-hash" version = "0.1.1" @@ -2723,9 +2506,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.74" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] @@ -2747,10 +2530,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools", + "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -2759,7 +2542,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "057237efdb71cf4b3f9396302a3d6599a92fa94063ba537b66130980ea9909f3" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "logos", "miette", "once_cell", @@ -2816,21 +2599,6 @@ dependencies = [ "unicase", ] -[[package]] -name = "pwhash" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "419a3ad8fa9f9d445e69d9b185a24878ae6e6f55c96e4512f4a0e28cd3bc5c56" -dependencies = [ - "blowfish 0.7.0", - "byteorder", - "hmac", - "md-5 0.9.1", - "rand", - "sha-1", - "sha2 0.9.9", -] - [[package]] name = "quanta" version = "0.12.2" @@ -2861,18 +2629,6 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", "rand_core", ] @@ -2881,9 +2637,6 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] [[package]] name = "raw-cpuid" @@ -2969,6 +2722,12 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + [[package]] name = "regex-syntax" version = "0.8.2" @@ -2977,11 +2736,11 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", @@ -2999,7 +2758,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.9", + "rustls 0.21.10", "rustls-pemfile 1.0.4", "serde", "serde_json", @@ -3076,22 +2835,22 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.25" +version = "0.38.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" dependencies = [ "bitflags 2.4.1", "errno", "libc", - "linux-raw-sys 0.4.11", - "windows-sys 0.48.0", + "linux-raw-sys 0.4.12", + "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.21.9" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", "ring", @@ -3132,7 +2891,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", ] [[package]] @@ -3141,7 +2900,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35e4980fa29e4c4b212ffb3db068a564cbf560e51d3944b7c88bd8bf5bec64f4" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "rustls-pki-types", ] @@ -3180,9 +2939,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "same-file" @@ -3195,11 +2954,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3267,9 +3026,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" dependencies = [ "serde", ] @@ -3312,7 +3071,7 @@ checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -3382,9 +3141,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.27" +version = "0.9.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" +checksum = "b1bf28c79a99f70ee1f1d83d10c875d2e70618417fda01ad1785e027579d9d38" dependencies = [ "indexmap", "itoa", @@ -3393,43 +3152,6 @@ dependencies = [ "unsafe-libyaml", ] -[[package]] -name = "sha-1" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "sha2" version = "0.10.8" @@ -3438,7 +3160,7 @@ checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -3473,21 +3195,9 @@ dependencies = [ [[package]] name = "similar" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aeaf503862c419d66959f5d7ca015337d864e9c49485d771b732e2a20453597" - -[[package]] -name = "simple_asn1" -version = "0.6.2" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" -dependencies = [ - "num-bigint", - "num-traits", - "thiserror", - "time", -] +checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21" [[package]] name = "siphasher" @@ -3521,9 +3231,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "2593d31f82ead8df961d8bd23a64c2ccf2eb5dd34b0a34bfb4dd54011c72009e" [[package]] name = "socket2" @@ -3601,7 +3311,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -3623,9 +3333,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.46" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -3679,20 +3389,15 @@ dependencies = [ "futures-channel", "futures-timer", "futures-util", - "getrandom", - "headers", - "htpasswd-verify", "http-cache-reqwest", "httpmock", "hyper", "hyper-rustls 0.25.0", "indexmap", "inquire", - "jsonwebtoken", "log", "lru 0.12.1", "mimalloc", - "mime", "mini-v8", "moka", "nom", @@ -3733,15 +3438,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" dependencies = [ "cfg-if", "fastrand 2.0.1", "redox_syscall", - "rustix 0.38.25", - "windows-sys 0.48.0", + "rustix 0.38.30", + "windows-sys 0.52.0", ] [[package]] @@ -3757,9 +3462,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -3781,14 +3486,14 @@ checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] name = "time" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ "deranged", "itoa", @@ -3806,9 +3511,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" dependencies = [ "time-core", ] @@ -3874,7 +3579,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -3883,7 +3588,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.9", + "rustls 0.21.10", "tokio", ] @@ -3956,15 +3661,15 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee8098afad3fb0c54a9007aab6804558410503ad676d4633f9c2559a00ac0f" +checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "ttl_cache" @@ -3998,9 +3703,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" [[package]] name = "unicode-ident" @@ -4049,9 +3754,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -4088,9 +3793,9 @@ dependencies = [ [[package]] name = "value-bag" -version = "1.4.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a72e1902dde2bd6441347de2b70b7f5d59bf157c6c62f0c44572607a1d55bbe" +checksum = "7cdbaf5e132e593e9fc1de6a15bbec912395b11fb9719e061cf64f804524c503" [[package]] name = "version_check" @@ -4150,7 +3855,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", "wasm-bindgen-shared", ] @@ -4184,7 +3889,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4248,9 +3953,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.2" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" +checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" [[package]] name = "which" @@ -4261,7 +3966,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.25", + "rustix 0.38.30", ] [[package]] @@ -4297,11 +4002,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.0", ] [[package]] @@ -4322,6 +4027,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -4352,6 +4066,21 @@ dependencies = [ "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +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", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -4364,6 +4093,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -4376,6 +4111,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -4388,6 +4129,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -4400,6 +4147,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -4412,6 +4165,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -4424,6 +4183,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -4436,11 +4201,17 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "winnow" -version = "0.5.19" +version = "0.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" +checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" dependencies = [ "memchr", ] @@ -4508,7 +4279,7 @@ dependencies = [ "async-trait", "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-macro-support", @@ -4550,7 +4321,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ffcc79e75c..75885d3144 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,12 +77,6 @@ ttl_cache = "0.5.1" protox = "0.5.1" prost-reflect = { version = "0.12.0", features = ["serde"] } prost = "0.12.3" -headers = "0.3.9" # previous version until hyper is updated to 1+ -mime = "0.3.17" -getrandom = { version = "0.2.12", features = ["js"] } # required to make some other dependencies wasm friendly -htpasswd-verify = { version = "0.3.0", git = "https://github.com/twistedfall/htpasswd-verify", rev = "ff14703083cbd639f7d05622b398926f3e718d61" } # fork version that is wasm compatible -jsonwebtoken = "9.2.0" - [dev-dependencies] criterion = "0.5.1" @@ -104,6 +98,7 @@ default = [ "inquire", ] + [workspace] members = [".", "autogen", "cloudflare"] diff --git a/benches/impl_path_string_for_evaluation_context.rs b/benches/impl_path_string_for_evaluation_context.rs index fc2616486e..b0195a7942 100644 --- a/benches/impl_path_string_for_evaluation_context.rs +++ b/benches/impl_path_string_for_evaluation_context.rs @@ -9,7 +9,6 @@ use hyper::header::HeaderValue; use hyper::HeaderMap; use indexmap::IndexMap; use once_cell::sync::Lazy; -use tailcall::auth::context::AuthContext; use tailcall::blueprint::Server; use tailcall::chrono_cache::ChronoCache; use tailcall::cli::{init_env, init_http, init_http2_only}; @@ -141,13 +140,13 @@ fn assert_test(eval_ctx: &EvaluationContext<'_, MockGraphqlContext>) { fn request_context() -> RequestContext { let tailcall::config::Config { server, upstream, .. } = tailcall::config::Config::default(); + //TODO: default is used only in tests. Drop default and move it to test. let server = Server::try_from(server).unwrap(); let h_client = Arc::new(init_http(&upstream)); let h2_client = Arc::new(init_http2_only(&upstream)); RequestContext { req_headers: HeaderMap::new(), - allowed_headers: HeaderMap::new(), h_client, h2_client, server, @@ -159,12 +158,11 @@ fn request_context() -> RequestContext { min_max_age: Arc::new(Mutex::new(None)), cache_public: Arc::new(Mutex::new(None)), env_vars: Arc::new(init_env()), - auth_ctx: AuthContext::default(), } } fn bench_main(c: &mut Criterion) { - let mut req_ctx = request_context().allowed_headers(TEST_HEADERS.clone()); + let mut req_ctx = request_context().req_headers(TEST_HEADERS.clone()); req_ctx.server.vars = TEST_VARS.clone(); let eval_ctx = EvaluationContext::new(&req_ctx, &MockGraphqlContext); diff --git a/examples/.tailcallrc.graphql b/examples/.tailcallrc.graphql index b4aede7961..89aaad9d77 100644 --- a/examples/.tailcallrc.graphql +++ b/examples/.tailcallrc.graphql @@ -83,11 +83,6 @@ directive @server( `key` sets the path to key for running the server over HTTP2 (HTTPS). @default `null`. """ key: String - - """ - `auth` specified list of auth providers that could be used to verify access to protected fields (that marked with @protected) - """ - auth: [AuthProvider!] ) on SCHEMA enum HttpVersion { @@ -313,9 +308,7 @@ directive @cache( Specifies the duration, in milliseconds, of how long the value has to be stored in the cache. """ maxAge: Int! -) on FIELD_DEFINITION | OBJECT - -directive @protected on FIELD_DEFINITION | OBJECT +) on FIELD_DEFINITION """ Allows composing operators as simple expressions @@ -464,52 +457,4 @@ input Batch { headers: [String] } -input AuthBasic { - htpasswd: String -} - -input AuthJwksRemote { - url: String! - maxAge: Int -} - -input AuthJwks { - """ - JWKS data loaded from the remote server - """ - remote: AuthJwksRemote - """ - JWKS data as a string or a template - """ - data: String -} - -input AuthJWT { - issuer: String - audiences: [String!] - """ - Specifies if the kid value inside request's JWT token is required to get validated with the JWKS - """ - optionalKid: Boolean - """ - Specifies JWKS data that is used for JWT validation. More on [jwks](https://datatracker.ietf.org/doc/html/rfc7517). If you need to create JWKS from private key use tools like [this](https://russelldavies.github.io/jwk-creator/) - """ - jwks: AuthJwks! -} - -input AuthProvider { - """ - Unique id for the auth provider. For future use - """ - id: String! - """ - Settings for JWT auth provider - """ - jwt: AuthJWT - """ - Settings for Basic auth provider - """ - basic: AuthBasic -} - scalar JSON diff --git a/examples/.tailcallrc.schema.json b/examples/.tailcallrc.schema.json index 33171c2664..1b5c7703e8 100644 --- a/examples/.tailcallrc.schema.json +++ b/examples/.tailcallrc.schema.json @@ -16,20 +16,14 @@ "type": "array" } }, - "required": [ - "name", - "path" - ], + "required": ["name", "path"], "type": "object" }, "Arg": { "properties": { "default_value": true, "doc": { - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "list": { "type": "boolean" @@ -51,70 +45,9 @@ "type": "string" } }, - "required": [ - "type" - ], - "type": "object" - }, - "Auth": { - "items": { - "$ref": "#/definitions/AuthEntry" - }, - "type": "array" - }, - "AuthEntry": { - "oneOf": [ - { - "additionalProperties": false, - "properties": { - "jwt": { - "$ref": "#/definitions/Jwt" - } - }, - "required": [ - "jwt" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "basic": { - "$ref": "#/definitions/Basic" - } - }, - "required": [ - "basic" - ], - "type": "object" - } - ], - "properties": { - "id": { - "type": [ - "string", - "null" - ] - } - }, + "required": ["type"], "type": "object" }, - "Basic": { - "oneOf": [ - { - "additionalProperties": false, - "properties": { - "htpasswd": { - "type": "string" - } - }, - "required": [ - "htpasswd" - ], - "type": "object" - } - ] - }, "Batch": { "properties": { "delay": { @@ -150,9 +83,7 @@ "type": "integer" } }, - "required": [ - "maxAge" - ], + "required": ["maxAge"], "type": "object" }, "Const": { @@ -160,16 +91,11 @@ "properties": { "data": true }, - "required": [ - "data" - ], + "required": ["data"], "type": "object" }, "Encoding": { - "enum": [ - "ApplicationJson", - "ApplicationXWwwFormUrlencoded" - ], + "enum": ["ApplicationJson", "ApplicationXWwwFormUrlencoded"], "type": "string" }, "Expr": { @@ -184,9 +110,7 @@ "description": "Root of the expression AST" } }, - "required": [ - "body" - ], + "required": ["body"], "type": "object" }, "ExprBody": { @@ -199,9 +123,7 @@ "$ref": "#/definitions/Http" } }, - "required": [ - "http" - ], + "required": ["http"], "type": "object" }, { @@ -212,9 +134,7 @@ "$ref": "#/definitions/Grpc" } }, - "required": [ - "grpc" - ], + "required": ["grpc"], "type": "object" }, { @@ -225,9 +145,7 @@ "$ref": "#/definitions/GraphQL" } }, - "required": [ - "graphQL" - ], + "required": ["graphQL"], "type": "object" }, { @@ -236,9 +154,7 @@ "properties": { "const": true }, - "required": [ - "const" - ], + "required": ["const"], "type": "object" }, { @@ -272,17 +188,11 @@ "description": "Expression to evaluate if the condition is true" } }, - "required": [ - "cond", - "else", - "then" - ], + "required": ["cond", "else", "then"], "type": "object" } }, - "required": [ - "if" - ], + "required": ["if"], "type": "object" }, { @@ -295,9 +205,7 @@ "type": "array" } }, - "required": [ - "and" - ], + "required": ["and"], "type": "object" }, { @@ -310,9 +218,7 @@ "type": "array" } }, - "required": [ - "or" - ], + "required": ["or"], "type": "object" }, { @@ -345,9 +251,7 @@ "type": "array" } }, - "required": [ - "cond" - ], + "required": ["cond"], "type": "object" }, { @@ -367,9 +271,7 @@ "type": "array" } }, - "required": [ - "defaultTo" - ], + "required": ["defaultTo"], "type": "object" }, { @@ -379,9 +281,7 @@ "$ref": "#/definitions/ExprBody" } }, - "required": [ - "isEmpty" - ], + "required": ["isEmpty"], "type": "object" }, { @@ -391,9 +291,7 @@ "$ref": "#/definitions/ExprBody" } }, - "required": [ - "not" - ], + "required": ["not"], "type": "object" }, { @@ -406,9 +304,7 @@ "type": "array" } }, - "required": [ - "concat" - ], + "required": ["concat"], "type": "object" }, { @@ -421,9 +317,7 @@ "type": "array" } }, - "required": [ - "intersection" - ], + "required": ["intersection"], "type": "object" }, { @@ -449,9 +343,7 @@ "type": "array" } }, - "required": [ - "difference" - ], + "required": ["difference"], "type": "object" }, { @@ -471,9 +363,7 @@ "type": "array" } }, - "required": [ - "eq" - ], + "required": ["eq"], "type": "object" }, { @@ -493,9 +383,7 @@ "type": "array" } }, - "required": [ - "gt" - ], + "required": ["gt"], "type": "object" }, { @@ -515,9 +403,7 @@ "type": "array" } }, - "required": [ - "gte" - ], + "required": ["gte"], "type": "object" }, { @@ -537,9 +423,7 @@ "type": "array" } }, - "required": [ - "lt" - ], + "required": ["lt"], "type": "object" }, { @@ -559,9 +443,7 @@ "type": "array" } }, - "required": [ - "lte" - ], + "required": ["lte"], "type": "object" }, { @@ -574,9 +456,7 @@ "type": "array" } }, - "required": [ - "max" - ], + "required": ["max"], "type": "object" }, { @@ -589,9 +469,7 @@ "type": "array" } }, - "required": [ - "min" - ], + "required": ["min"], "type": "object" }, { @@ -617,9 +495,7 @@ "type": "array" } }, - "required": [ - "pathEq" - ], + "required": ["pathEq"], "type": "object" }, { @@ -642,9 +518,7 @@ "type": "array" } }, - "required": [ - "propEq" - ], + "required": ["propEq"], "type": "object" }, { @@ -667,9 +541,7 @@ "type": "array" } }, - "required": [ - "sortPath" - ], + "required": ["sortPath"], "type": "object" }, { @@ -695,9 +567,7 @@ "type": "array" } }, - "required": [ - "symmetricDifference" - ], + "required": ["symmetricDifference"], "type": "object" }, { @@ -723,9 +593,7 @@ "type": "array" } }, - "required": [ - "union" - ], + "required": ["union"], "type": "object" }, { @@ -745,9 +613,7 @@ "type": "array" } }, - "required": [ - "mod" - ], + "required": ["mod"], "type": "object" }, { @@ -767,9 +633,7 @@ "type": "array" } }, - "required": [ - "add" - ], + "required": ["add"], "type": "object" }, { @@ -779,9 +643,7 @@ "$ref": "#/definitions/ExprBody" } }, - "required": [ - "dec" - ], + "required": ["dec"], "type": "object" }, { @@ -801,9 +663,7 @@ "type": "array" } }, - "required": [ - "divide" - ], + "required": ["divide"], "type": "object" }, { @@ -813,9 +673,7 @@ "$ref": "#/definitions/ExprBody" } }, - "required": [ - "inc" - ], + "required": ["inc"], "type": "object" }, { @@ -835,9 +693,7 @@ "type": "array" } }, - "required": [ - "multiply" - ], + "required": ["multiply"], "type": "object" }, { @@ -847,9 +703,7 @@ "$ref": "#/definitions/ExprBody" } }, - "required": [ - "negate" - ], + "required": ["negate"], "type": "object" }, { @@ -862,9 +716,7 @@ "type": "array" } }, - "required": [ - "product" - ], + "required": ["product"], "type": "object" }, { @@ -884,9 +736,7 @@ "type": "array" } }, - "required": [ - "subtract" - ], + "required": ["subtract"], "type": "object" }, { @@ -899,9 +749,7 @@ "type": "array" } }, - "required": [ - "sum" - ], + "required": ["sum"], "type": "object" } ] @@ -940,10 +788,7 @@ }, "doc": { "description": "Publicly visible documentation for the field.", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "expr": { "anyOf": [ @@ -1019,10 +864,6 @@ ], "description": "Omits a field from public consumption." }, - "protected": { - "default": false, - "type": "boolean" - }, "required": { "description": "Flag to indicate the type is required.", "type": "boolean" @@ -1061,10 +902,7 @@ }, "baseURL": { "description": "This refers to the base URL of the API. If not specified, the default base URL is the one specified in the `@upstream` operator.", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "batch": { "description": "If the upstream GraphQL server supports request batching, you can specify the 'batch' argument to batch several requests into a single batch request.\n\nMake sure you have also specified batch settings to the `@upstream` and to the `@graphQL` operator.", @@ -1083,9 +921,7 @@ "type": "string" } }, - "required": [ - "name" - ], + "required": ["name"], "type": "object" }, "Grpc": { @@ -1093,17 +929,11 @@ "properties": { "baseURL": { "description": "This refers to the base URL of the API. If not specified, the default base URL is the one specified in the `@upstream` operator", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "body": { "description": "This refers to the arguments of your gRPC call. You can pass it as a static object or use Mustache template for dynamic parameters. These parameters will be added in the body in `protobuf` format.", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "groupBy": { "description": "The key path in the response which should be used to group multiple requests. For instance `[\"news\",\"id\"]`. For more details please refer out [n + 1 guide](https://tailcall.run/docs/guides/n+1#solving-using-batching).", @@ -1133,11 +963,7 @@ "type": "string" } }, - "required": [ - "method", - "protoPath", - "service" - ], + "required": ["method", "protoPath", "service"], "type": "object" }, "Http": { @@ -1145,17 +971,11 @@ "properties": { "baseURL": { "description": "This refers to the base URL of the API. If not specified, the default base URL is the one specified in the `@upstream` operator", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "body": { "description": "The body of the API call. It's used for methods like POST or PUT that send data to the server. You can pass it as a static object or use a Mustache template to substitute variables from the GraphQL variables.", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "encoding": { "allOf": [ @@ -1223,16 +1043,11 @@ "description": "This represents the query parameters of your API call. You can pass it as a static object or use Mustache template for dynamic parameters. These parameters will be added to the URL." } }, - "required": [ - "path" - ], + "required": ["path"], "type": "object" }, "HttpVersion": { - "enum": [ - "HTTP1", - "HTTP2" - ], + "enum": ["HTTP1", "HTTP2"], "type": "string" }, "JS": { @@ -1241,78 +1056,7 @@ "type": "string" } }, - "required": [ - "script" - ], - "type": "object" - }, - "Jwks": { - "oneOf": [ - { - "additionalProperties": false, - "properties": { - "data": { - "type": "string" - } - }, - "required": [ - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "remote": { - "properties": { - "maxAge": { - "default": 300000, - "format": "uint64", - "minimum": 1.0, - "type": "integer" - }, - "url": { - "type": "string" - } - }, - "required": [ - "url" - ], - "type": "object" - } - }, - "required": [ - "remote" - ], - "type": "object" - } - ] - }, - "Jwt": { - "properties": { - "audiences": { - "items": { - "type": "string" - }, - "type": "array", - "uniqueItems": true - }, - "issuer": { - "type": [ - "string", - "null" - ] - }, - "jwks": { - "$ref": "#/definitions/Jwks" - }, - "optionalKid": { - "type": "boolean" - } - }, - "required": [ - "jwks" - ], + "required": ["script"], "type": "object" }, "KeyValues": { @@ -1322,26 +1066,13 @@ "type": "object" }, "Method": { - "enum": [ - "GET", - "POST", - "PUT", - "PATCH", - "DELETE", - "HEAD", - "OPTIONS", - "CONNECT", - "TRACE" - ], + "enum": ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "CONNECT", "TRACE"], "type": "string" }, "Modify": { "properties": { "name": { - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "omit": { "type": "boolean" @@ -1358,30 +1089,19 @@ "type": "string" } }, - "required": [ - "url" - ], + "required": ["url"], "type": "object" }, "RootSchema": { "properties": { "mutation": { - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "query": { - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "subscription": { - "type": [ - "string", - "null" - ] + "type": ["string", "null"] } }, "type": "object" @@ -1391,92 +1111,53 @@ "properties": { "apolloTracing": { "description": "`apolloTracing` exposes GraphQL query performance data, including execution time of queries and individual resolvers.", - "type": [ - "boolean", - "null" - ] - }, - "auth": { - "$ref": "#/definitions/Auth" + "type": ["boolean", "null"] }, "batchRequests": { "description": "`batchRequests` combines multiple requests into one, improving performance but potentially introducing latency and complicating debugging. Use judiciously. @default `false`", - "type": [ - "boolean", - "null" - ] + "type": ["boolean", "null"] }, "cacheControlHeader": { "description": "`cacheControlHeader` sends `Cache-Control` headers in responses when activated. The `max-age` value is the least of the values received from upstream services. @default `false`.", - "type": [ - "boolean", - "null" - ] + "type": ["boolean", "null"] }, "cert": { "description": "`cert` sets the path to certificate(s) for running the server over HTTP2 (HTTPS). @default `null`.", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "globalResponseTimeout": { "description": "`globalResponseTimeout` sets the maximum query duration before termination, acting as a safeguard against long-running queries.", "format": "int64", - "type": [ - "integer", - "null" - ] + "type": ["integer", "null"] }, "graphiql": { "description": "`graphiql` activates the GraphiQL IDE at the root path within Tailcall, a tool for query development and testing. @default `false`.", - "type": [ - "boolean", - "null" - ] + "type": ["boolean", "null"] }, "hostname": { "description": "`hostname` sets the server hostname.", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "introspection": { "description": "`introspection` allows clients to fetch schema information directly, aiding tools and applications in understanding available types, fields, and operations. @default `true`.", - "type": [ - "boolean", - "null" - ] + "type": ["boolean", "null"] }, "key": { "description": "`key` sets the path to key for running the server over HTTP2 (HTTPS). @default `null`.", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "pipelineFlush": { - "type": [ - "boolean", - "null" - ] + "type": ["boolean", "null"] }, "port": { "description": "`port` sets the Tailcall running port. @default `8000`.", "format": "uint16", "minimum": 0.0, - "type": [ - "integer", - "null" - ] + "type": ["integer", "null"] }, "queryValidation": { "description": "`queryValidation` checks incoming GraphQL queries against the schema, preventing errors from invalid queries. Can be disabled for performance. @default `false`.", - "type": [ - "boolean", - "null" - ] + "type": ["boolean", "null"] }, "responseHeaders": { "allOf": [ @@ -1488,10 +1169,7 @@ }, "responseValidation": { "description": "`responseValidation` Tailcall automatically validates responses from upstream services using inferred schema. @default `false`.", - "type": [ - "boolean", - "null" - ] + "type": ["boolean", "null"] }, "vars": { "allOf": [ @@ -1516,10 +1194,7 @@ "description": "`workers` sets the number of worker threads. @default the number of system cores.", "format": "uint", "minimum": 0.0, - "type": [ - "integer", - "null" - ] + "type": ["integer", "null"] } }, "type": "object" @@ -1548,20 +1223,14 @@ }, "doc": { "description": "Documentation for the type that is publicly visible.", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "enum": { "description": "Variants for the type if it's an enum", "items": { "type": "string" }, - "type": [ - "array", - "null" - ], + "type": ["array", "null"], "uniqueItems": true }, "fields": { @@ -1583,27 +1252,18 @@ "description": "Flag to indicate if the type is an interface.", "type": "boolean" }, - "protected": { - "default": false, - "type": "boolean" - }, "scalar": { "description": "Flag to indicate if the type is a scalar.", "type": "boolean" } }, - "required": [ - "fields" - ], + "required": ["fields"], "type": "object" }, "Union": { "properties": { "doc": { - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "types": { "items": { @@ -1613,9 +1273,7 @@ "uniqueItems": true } }, - "required": [ - "types" - ], + "required": ["types"], "type": "object" }, "Upstream": { @@ -1626,18 +1284,12 @@ "items": { "type": "string" }, - "type": [ - "array", - "null" - ], + "type": ["array", "null"], "uniqueItems": true }, "baseURL": { "description": "This refers to the default base URL for your APIs. If it's not explicitly mentioned in the `@upstream` operator, then each [@http](#http) operator must specify its own `baseURL`. If neither `@upstream` nor [@http](#http) provides a `baseURL`, it results in a compilation error.", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "batch": { "anyOf": [ @@ -1654,67 +1306,43 @@ "description": "The time in seconds that the connection will wait for a response before timing out.", "format": "uint64", "minimum": 0.0, - "type": [ - "integer", - "null" - ] + "type": ["integer", "null"] }, "http2Only": { "description": "The `http2Only` setting allows you to specify whether the client should always issue HTTP2 requests, without checking if the server supports it or not. By default it is set to `false` for all HTTP requests made by the server, but is automatically set to true for GRPC.", - "type": [ - "boolean", - "null" - ] + "type": ["boolean", "null"] }, "httpCache": { "description": "Activating this enables Tailcall's HTTP caching, adhering to the [HTTP Caching RFC](https://tools.ietf.org/html/rfc7234), to enhance performance by minimizing redundant data fetches. Defaults to `false` if unspecified.", - "type": [ - "boolean", - "null" - ] + "type": ["boolean", "null"] }, "keepAliveInterval": { "description": "The time in seconds between each keep-alive message sent to maintain the connection.", "format": "uint64", "minimum": 0.0, - "type": [ - "integer", - "null" - ] + "type": ["integer", "null"] }, "keepAliveTimeout": { "description": "The time in seconds that the connection will wait for a keep-alive message before closing.", "format": "uint64", "minimum": 0.0, - "type": [ - "integer", - "null" - ] + "type": ["integer", "null"] }, "keepAliveWhileIdle": { "description": "A boolean value that determines whether keep-alive messages should be sent while the connection is idle.", - "type": [ - "boolean", - "null" - ] + "type": ["boolean", "null"] }, "poolIdleTimeout": { "description": "The time in seconds that the connection pool will wait before closing idle connections.", "format": "uint64", "minimum": 0.0, - "type": [ - "integer", - "null" - ] + "type": ["integer", "null"] }, "poolMaxIdlePerHost": { "description": "The maximum number of idle connections that will be maintained per host.", "format": "uint", "minimum": 0.0, - "type": [ - "integer", - "null" - ] + "type": ["integer", "null"] }, "proxy": { "anyOf": [ @@ -1731,26 +1359,17 @@ "description": "The time in seconds between each TCP keep-alive message sent to maintain the connection.", "format": "uint64", "minimum": 0.0, - "type": [ - "integer", - "null" - ] + "type": ["integer", "null"] }, "timeout": { "description": "The maximum time in seconds that the connection will wait for a response.", "format": "uint64", "minimum": 0.0, - "type": [ - "integer", - "null" - ] + "type": ["integer", "null"] }, "userAgent": { "description": "The User-Agent header value to be used in HTTP requests. @default `Tailcall/1.0`", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] } }, "type": "object" @@ -1758,11 +1377,7 @@ "schema": { "oneOf": [ { - "enum": [ - "Str", - "Num", - "Bool" - ], + "enum": ["Str", "Num", "Bool"], "type": "string" }, { @@ -1775,9 +1390,7 @@ "type": "object" } }, - "required": [ - "Obj" - ], + "required": ["Obj"], "type": "object" }, { @@ -1787,9 +1400,7 @@ "$ref": "#/definitions/schema" } }, - "required": [ - "Arr" - ], + "required": ["Arr"], "type": "object" }, { @@ -1799,9 +1410,7 @@ "$ref": "#/definitions/schema" } }, - "required": [ - "Opt" - ], + "required": ["Opt"], "type": "object" } ] @@ -1850,9 +1459,7 @@ "description": "Dictates how tailcall should handle upstream requests/responses. Tuning upstream can improve performance and reliability for connections." } }, - "required": [ - "schema" - ], + "required": ["schema"], "title": "Config", "type": "object" -} \ No newline at end of file +} diff --git a/examples/auth.graphql b/examples/auth.graphql deleted file mode 100644 index 03a077d9b6..0000000000 --- a/examples/auth.graphql +++ /dev/null @@ -1,53 +0,0 @@ -schema - @server( - port: 8000 - graphiql: true - vars: [ - { - key: "BASIC_AUTH" - value: """ - testuser1:$apr1$e3dp9qh2$fFIfHU9bilvVZBl8TxKzL/ - testuser2:$2y$10$wJ/mZDURcAOBIrswCAKFsO0Nk7BpHmWl/XuhF7lNm3gBAFH3ofsuu - testuser3:{SHA}Y2fEjdGT1W6nsLqtJbGUVeUp9e4= - """ - } - ] - auth: [ - {id: "basic-1", basic: {htpasswd: "{{vars.BASIC_AUTH}}"}} - { - id: "jwt-1" - jwt: { - jwks: { - remote: { - url: "https://gist.githubusercontent.com/meskill/b0e2343c4aa3e0af95ca0c9209b5818a/raw/tailcall-auth-jwt-jwks-example.json" - } - } - } - } - ] - ) - @upstream(baseURL: "http://jsonplaceholder.typicode.com", httpCache: true) { - query: Query -} - -type Query { - posts: [Post] @http(path: "/posts") - user(id: Int!): User @http(path: "/users/{{args.id}}") -} - -type User @protected { - id: Int! - name: String! - username: String! - email: String! - phone: String - website: String -} - -type Post { - id: Int! - userId: Int! - title: String! - body: String! @protected - user: User @http(path: "/users/{{value.userId}}") -} diff --git a/src/app_context.rs b/src/app_context.rs index 15afe48659..dd62b58b71 100644 --- a/src/app_context.rs +++ b/src/app_context.rs @@ -4,7 +4,6 @@ use async_graphql::dynamic::{self, DynamicRequest}; use async_graphql::Response; use async_graphql_value::ConstValue; -use crate::auth::context::GlobalAuthContext; use crate::blueprint::Type::ListType; use crate::blueprint::{Blueprint, Definition}; use crate::chrono_cache::ChronoCache; @@ -22,10 +21,9 @@ pub struct AppContext { pub blueprint: Blueprint, pub http_data_loaders: Arc>>, pub gql_data_loaders: Arc>>, - pub grpc_data_loaders: Arc>>, pub cache: ChronoCache, + pub grpc_data_loaders: Arc>>, pub env_vars: Arc, - pub auth_ctx: Arc, } impl AppContext { @@ -96,10 +94,6 @@ impl AppContext { let schema = blueprint.to_schema(); - let auth = blueprint.server.auth.clone(); - - let auth_ctx = GlobalAuthContext::new(auth, h_client.clone()); - AppContext { schema, universal_http_client: h_client, @@ -110,7 +104,6 @@ impl AppContext { cache: ChronoCache::new(), grpc_data_loaders: Arc::new(grpc_data_loaders), env_vars: env, - auth_ctx: Arc::new(auth_ctx), } } diff --git a/src/auth/basic.rs b/src/auth/basic.rs deleted file mode 100644 index 1916898c4e..0000000000 --- a/src/auth/basic.rs +++ /dev/null @@ -1,86 +0,0 @@ -use headers::authorization::Basic; -use headers::{Authorization, HeaderMapExt}; -use htpasswd_verify::Htpasswd; - -use super::error::Error; -use super::verify::Verify; -use crate::blueprint; -use crate::http::RequestContext; - -pub struct BasicVerifier { - verifier: Htpasswd<'static>, -} - -impl Verify for BasicVerifier { - /// Verify the request context against the basic auth provider. - async fn verify(&self, req_ctx: &RequestContext) -> Result<(), Error> { - let header = req_ctx.req_headers.typed_get::>(); - - let Some(header) = header else { - return Err(Error::Missing); - }; - - if self.verifier.check(header.username(), header.password()) { - Ok(()) - } else { - Err(Error::Invalid) - } - } -} - -impl BasicVerifier { - pub fn new(options: blueprint::BasicProvider) -> Self { - Self { verifier: Htpasswd::new_owned(&options.htpasswd) } - } -} - -#[cfg(test)] -pub mod tests { - use super::*; - - // testuser1:password123 - // testuser2:mypassword - // testuser3:abc123 - pub static HTPASSWD_TEST: &str = " -testuser1:$apr1$e3dp9qh2$fFIfHU9bilvVZBl8TxKzL/ -testuser2:$2y$10$wJ/mZDURcAOBIrswCAKFsO0Nk7BpHmWl/XuhF7lNm3gBAFH3ofsuu -testuser3:{SHA}Y2fEjdGT1W6nsLqtJbGUVeUp9e4= -"; - - pub fn create_basic_auth_request(username: &str, password: &str) -> RequestContext { - let mut req_context = RequestContext::default(); - - req_context - .req_headers - .typed_insert(Authorization::basic(username, password)); - - req_context - } - - #[tokio::test] - async fn verify_passwords() { - let provider = BasicVerifier::new(blueprint::BasicProvider { htpasswd: HTPASSWD_TEST.to_owned() }); - - let validation = provider.verify(&RequestContext::default()).await.err(); - assert_eq!(validation, Some(Error::Missing)); - - let validation = provider - .verify(&create_basic_auth_request("testuser1", "wrong-password")) - .await - .err(); - assert_eq!(validation, Some(Error::Invalid)); - - let validation = provider - .verify(&create_basic_auth_request("testuser1", "password123")) - .await; - assert!(validation.is_ok()); - - let validation = provider - .verify(&create_basic_auth_request("testuser2", "mypassword")) - .await; - assert!(validation.is_ok()); - - let validation = provider.verify(&create_basic_auth_request("testuser3", "abc123")).await; - assert!(validation.is_ok()); - } -} diff --git a/src/auth/context.rs b/src/auth/context.rs deleted file mode 100644 index 9d5212df6c..0000000000 --- a/src/auth/context.rs +++ /dev/null @@ -1,125 +0,0 @@ -use std::sync::{Arc, Mutex}; - -use futures_util::future::join_all; - -use super::error::Error; -use super::verify::{AuthVerifier, Verify}; -use crate::blueprint::Auth; -use crate::http::RequestContext; -use crate::HttpIO; - -#[derive(Default)] -pub struct GlobalAuthContext { - providers: Vec, -} - -#[derive(Default)] -pub struct AuthContext { - // TODO: can we do without mutex? - auth_result: Mutex>>, - global_ctx: Arc, -} - -impl GlobalAuthContext { - // TODO: it could be better to return async_graphql::Error to make it more graphql way - // with additional info. But this actually requires rewrites to expression to work with that type - // since otherwise any additional info will be lost during conversion to anyhow::Error - async fn validate(&self, request: &RequestContext) -> Result<(), Error> { - let validations = join_all(self.providers.iter().map(|provider| provider.verify(request))).await; - - let mut error = Error::Missing; - - for v in validations { - let Err(err) = v else { - return Ok(()); - }; - - if err > error { - error = err; - } - } - - Err(error) - } -} - -impl GlobalAuthContext { - pub fn new(auth: Auth, client: Arc) -> Self { - let providers = auth - .0 - .into_iter() - .map(|provider| AuthVerifier::from_config(provider.provider, client.clone())) - .collect(); - - Self { providers } - } -} - -impl AuthContext { - pub async fn validate(&self, request: &RequestContext) -> Result<(), Error> { - if let Some(result) = self.auth_result.lock().unwrap().as_ref() { - return result.clone(); - } - - let result = self.global_ctx.validate(request).await; - - self.auth_result.lock().unwrap().replace(result.clone()); - - result - } -} - -impl From<&Arc> for AuthContext { - fn from(global_ctx: &Arc) -> Self { - Self { global_ctx: global_ctx.clone(), auth_result: Default::default() } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::auth::basic::tests::{create_basic_auth_request, HTPASSWD_TEST}; - use crate::auth::basic::BasicVerifier; - use crate::auth::jwt::jwt_verify::tests::{create_jwt_auth_request, JWT_VALID_TOKEN_WITH_KID}; - use crate::auth::jwt::jwt_verify::JwtVerifier; - use crate::blueprint; - use crate::http::Response; - - struct MockHttpClient; - - #[async_trait::async_trait] - impl HttpIO for MockHttpClient { - async fn execute(&self, _request: reqwest::Request) -> anyhow::Result> { - todo!() - } - } - - #[tokio::test] - async fn validate_request() { - let basic_provider = BasicVerifier::new(blueprint::BasicProvider { htpasswd: HTPASSWD_TEST.to_owned() }); - let jwt_options = blueprint::JwtProvider::test_value(); - let jwt_provider = JwtVerifier::new(jwt_options, Arc::new(MockHttpClient)); - - let auth_context = - GlobalAuthContext { providers: vec![AuthVerifier::Basic(basic_provider), AuthVerifier::Jwt(jwt_provider)] }; - - let validation = auth_context.validate(&RequestContext::default()).await.err(); - assert_eq!(validation, Some(Error::Missing)); - - let validation = auth_context - .validate(&create_basic_auth_request("testuser1", "wrong-password")) - .await - .err(); - assert_eq!(validation, Some(Error::Invalid)); - - let validation = auth_context - .validate(&create_basic_auth_request("testuser1", "password123")) - .await; - assert!(validation.is_ok()); - - let validation = auth_context - .validate(&create_jwt_auth_request(JWT_VALID_TOKEN_WITH_KID)) - .await; - assert!(validation.is_ok()); - } -} diff --git a/src/auth/error.rs b/src/auth/error.rs deleted file mode 100644 index 24bdea1308..0000000000 --- a/src/auth/error.rs +++ /dev/null @@ -1,11 +0,0 @@ -#[derive(Debug, thiserror::Error, Clone, PartialEq, PartialOrd)] -pub enum Error { - #[error("Haven't found auth parameters")] - Missing, - #[error("Couldn't validate auth request")] - // in case we haven't managed to actually validate the request - // and have failed somewhere else, usually while executing request - ValidationCheckFailed, - #[error("Auth validation failed")] - Invalid, -} diff --git a/src/auth/jwt/jwks.rs b/src/auth/jwt/jwks.rs deleted file mode 100644 index e67ec12937..0000000000 --- a/src/auth/jwt/jwks.rs +++ /dev/null @@ -1,102 +0,0 @@ -use std::str::FromStr; - -use anyhow::Result; -use derive_setters::Setters; -use jsonwebtoken::jwk::{Jwk, JwkSet}; -use jsonwebtoken::{decode, decode_header, Algorithm, DecodingKey, Validation}; - -use super::jwt_verify::JwtClaim; -use crate::auth::error::Error; - -#[derive(Setters)] -pub struct Jwks { - set: JwkSet, - optional_kid: bool, -} - -impl From for Jwks { - fn from(set: JwkSet) -> Self { - Self { set, optional_kid: false } - } -} - -impl Jwks { - fn decode_with_jwk(&self, token: &str, jwk: &Jwk) -> Result { - let key = DecodingKey::from_jwk(jwk).map_err(|_| Error::ValidationCheckFailed)?; - let algorithm = jwk - .common - .key_algorithm - .and_then(|alg| Algorithm::from_str(alg.to_string().as_str()).ok()) - .ok_or(Error::ValidationCheckFailed)?; - let mut validation = Validation::new(algorithm); - - // will validate on our side later - validation.validate_aud = false; - - let decoded = decode::(token, &key, &validation).map_err(|_| Error::Invalid)?; - - Ok(decoded.claims) - } - - pub fn decode(&self, token: &str) -> Result { - let header = decode_header(token).map_err(|_| Error::Invalid)?; - - if let Some(kid) = &header.kid { - let jwk = self.set.find(kid).ok_or(Error::ValidationCheckFailed)?; - - self.decode_with_jwk(token, jwk) - } else { - if !self.optional_kid { - return Err(Error::Invalid); - } - - // iterate over all available jwk and try to decode incoming token with it - // if any succeeds return the data - for jwk in self.set.keys.iter() { - if let Ok(claims) = self.decode_with_jwk(token, jwk) { - return Ok(claims); - } - } - - Err(Error::Invalid) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::auth::jwt::jwt_verify::tests::{JWK_SET, JWT_VALID_TOKEN_NO_KID, JWT_VALID_TOKEN_WITH_KID}; - use crate::auth::jwt::jwt_verify::OneOrMany; - - #[test] - fn test_decode_required_kid() { - let jwks = Jwks::from(JWK_SET.clone()); - - assert!(matches!(jwks.decode(""), Err(Error::Invalid))); - - let data = jwks.decode(JWT_VALID_TOKEN_WITH_KID).unwrap(); - - assert!(matches!(data.aud, Some(OneOrMany::Vec(v)) if v == ["them"])); - assert!(matches!(data.iss, Some(v) if v == "me")); - - assert!(matches!(jwks.decode(JWT_VALID_TOKEN_NO_KID), Err(Error::Invalid))); - } - - #[test] - fn test_decode_optional_kid() { - let jwks = Jwks::from(JWK_SET.clone()).optional_kid(true); - - assert!(matches!(jwks.decode(""), Err(Error::Invalid))); - - let data = jwks.decode(JWT_VALID_TOKEN_WITH_KID).unwrap(); - - assert!(matches!(data.aud, Some(OneOrMany::Vec(v)) if v == ["them"])); - assert!(matches!(data.iss, Some(v) if v == "me")); - - let data = jwks.decode(JWT_VALID_TOKEN_NO_KID).unwrap(); - - assert!(matches!(data.aud, Some(OneOrMany::One(v)) if v == "some")); - assert!(matches!(data.iss, Some(v) if v == "me")); - } -} diff --git a/src/auth/jwt/jwks_decoder.rs b/src/auth/jwt/jwks_decoder.rs deleted file mode 100644 index ca64120c0b..0000000000 --- a/src/auth/jwt/jwks_decoder.rs +++ /dev/null @@ -1,32 +0,0 @@ -use std::sync::Arc; - -use super::jwks::Jwks; -use super::jwks_remote::JwksRemote; -use super::jwt_verify::JwtClaim; -use crate::auth::error::Error; -use crate::{blueprint, HttpIO}; - -pub enum JwksDecoder { - Local(Jwks), - Remote(JwksRemote), -} - -impl JwksDecoder { - pub fn new(options: &blueprint::JwtProvider, client: Arc) -> Self { - match &options.jwks { - blueprint::Jwks::Local(jwks) => Self::Local(Jwks::from(jwks.clone()).optional_kid(options.optional_kid)), - blueprint::Jwks::Remote { url, max_age } => { - let decoder = JwksRemote::new(url.clone(), client, *max_age); - - Self::Remote(decoder.optional_kid(options.optional_kid)) - } - } - } - - pub async fn decode(&self, token: &str) -> Result { - match self { - JwksDecoder::Local(decoder) => decoder.decode(token), - JwksDecoder::Remote(verifier) => verifier.decode(token).await, - } - } -} diff --git a/src/auth/jwt/jwks_remote.rs b/src/auth/jwt/jwks_remote.rs deleted file mode 100644 index 45d9c8e796..0000000000 --- a/src/auth/jwt/jwks_remote.rs +++ /dev/null @@ -1,84 +0,0 @@ -use std::sync::{Arc, RwLock}; -use std::time::{Duration, Instant}; - -use hyper::header::HeaderValue; -use hyper::Method; -use jsonwebtoken::jwk::JwkSet; -use reqwest::Request; -use url::Url; - -use super::jwks::Jwks; -use super::jwt_verify::JwtClaim; -use crate::auth::error::Error; -use crate::HttpIO; - -struct JwksCache { - jwks: Jwks, - expiration: Instant, -} - -pub struct JwksRemote { - url: Url, - // as a trait object due to deep bubbling of generic definition - // up to the entry point - client: Arc, - max_age: Duration, - cache: RwLock>, - optional_kid: bool, -} - -impl JwksRemote { - pub fn new(url: Url, client: Arc, max_age: Duration) -> Self { - Self { url, client, max_age, cache: RwLock::new(None), optional_kid: false } - } - - /// If called with `true`, subsequent `decode` calls will - /// try all keys from the key set if a `kid` is not specified in the token. - pub fn optional_kid(mut self, optional: bool) -> Self { - self.optional_kid = optional; - - self - } - - pub async fn decode(&self, token: &str) -> Result { - { - let cache = self.cache.read().unwrap(); - - if let Some(c) = cache.as_ref() { - if c.expiration > Instant::now() { - return c.jwks.decode(token); - } - } - } - - let jwks = self.request_jwks().await.map_err(|_| Error::ValidationCheckFailed)?; - - let mut cache = self.cache.write().unwrap(); - if let Some(c) = cache.as_ref() { - if c.expiration > Instant::now() { - return c.jwks.decode(token); - } - } - - *cache = Some(JwksCache { - jwks: { - let v = Jwks::from(jwks); - v.optional_kid(self.optional_kid) - }, - expiration: std::time::Instant::now() + self.max_age, - }); - - cache.as_ref().unwrap().jwks.decode(token).map_err(|_| Error::Invalid) - } - - async fn request_jwks(&self) -> anyhow::Result { - let mut request = Request::new(Method::GET, self.url.clone()); - - request - .headers_mut() - .insert("accept", HeaderValue::from_static(mime::APPLICATION_JSON.as_ref())); - - let response = self.client.execute(request).await?; - Ok(response.to_json()?.body) - } -} diff --git a/src/auth/jwt/jwt_verify.rs b/src/auth/jwt/jwt_verify.rs deleted file mode 100644 index 031a393a41..0000000000 --- a/src/auth/jwt/jwt_verify.rs +++ /dev/null @@ -1,306 +0,0 @@ -use std::sync::Arc; - -use headers::authorization::Bearer; -use headers::{Authorization, HeaderMapExt}; -use serde::Deserialize; - -use super::jwks_decoder::JwksDecoder; -use crate::auth::error::Error; -use crate::auth::verify::Verify; -use crate::http::RequestContext; -use crate::{blueprint, HttpIO}; - -#[derive(Debug, Deserialize)] -#[serde(untagged)] -pub enum OneOrMany { - One(T), - Vec(Vec), -} - -#[derive(Debug, Default, Deserialize)] -pub struct JwtClaim { - pub aud: Option>, - pub iss: Option, -} - -pub struct JwtVerifier { - options: blueprint::JwtProvider, - decoder: JwksDecoder, -} - -impl JwtVerifier { - pub fn new(options: blueprint::JwtProvider, client: Arc) -> Self { - Self { decoder: JwksDecoder::new(&options, client), options } - } - - fn resolve_token(&self, request: &RequestContext) -> Option { - let value = request.req_headers.typed_get::>(); - - value.map(|token| token.token().to_owned()) - } - - async fn validate_token(&self, token: &str) -> Result<(), Error> { - let claims = self - .decoder - .decode(token) - .await - .map_err(|_| Error::ValidationCheckFailed)?; - - self.validate_claims(&claims) - } - - fn validate_claims(&self, claims: &JwtClaim) -> Result<(), Error> { - if !validate_iss(&self.options, claims) || !validate_aud(&self.options, claims) { - return Err(Error::Invalid); - } - - Ok(()) - } -} - -impl Verify for JwtVerifier { - async fn verify(&self, request: &RequestContext) -> Result<(), Error> { - let token = self.resolve_token(request); - - let Some(token) = token else { - return Err(Error::Missing); - }; - - self.validate_token(&token).await - } -} - -pub fn validate_iss(options: &blueprint::JwtProvider, claims: &JwtClaim) -> bool { - options - .issuer - .as_ref() - .map(|issuer| claims.iss.as_ref().map(|iss| iss == issuer).unwrap_or(false)) - .unwrap_or(true) -} - -pub fn validate_aud(options: &blueprint::JwtProvider, claims: &JwtClaim) -> bool { - let audiences = &options.audiences; - - if audiences.is_empty() { - true - } else { - let Some(aud) = &claims.aud else { return false }; - - match aud { - OneOrMany::One(aud) => audiences.contains(aud), - // if user token has list of aud, validate that at least one of them is inside validation set - OneOrMany::Vec(auds) => auds.iter().any(|aud| audiences.contains(aud)), - } - } -} - -#[cfg(test)] -pub mod tests { - use std::collections::HashSet; - - use jsonwebtoken::jwk::JwkSet; - use once_cell::sync::Lazy; - - use super::*; - use crate::http::Response; - - struct MockHttpClient; - - #[async_trait::async_trait] - impl HttpIO for MockHttpClient { - async fn execute(&self, _request: reqwest::Request) -> anyhow::Result> { - todo!() - } - } - - // tokens are valid for 10 years. If it is expired, update it =) - // to parse the token and see its content use https://jwt.io - - // token with kid, issuer = "me" and audience = ["them"] - pub const JWT_VALID_TOKEN_WITH_KID: &str = "eyJhbGciOiJSUzI1NiIsImtpZCI6Ikk0OHFNSnA1NjZTU0tRb2dZWFl0SEJvOXE2WmNFS0hpeE5QZU5veFYxYzgifQ.eyJleHAiOjIwMTkwNTY0NDEuMCwiaXNzIjoibWUiLCJzdWIiOiJ5b3UiLCJhdWQiOlsidGhlbSJdfQ.cU-hJgVGWxK3-IBggYBChhf3FzibBKjuDLtq2urJ99FVXIGZls0VMXjyNW7yHhLLuif_9t2N5UIUIq-hwXVv7rrGRPCGrlqKU0jsUH251Spy7_ppG5_B2LsG3cBJcwkD4AVz8qjT3AaE_vYZ4WnH-CQ-F5Vm7wiYZgbdyU8xgKoH85KAxaCdJJlYOi8mApE9_zcdmTNJrTNd9sp7PX3lXSUu9AWlrZkyO-HhVbXFunVtfduDuTeVXxP8iw1wt6171CFbPmQJU_b3xCornzyFKmhSc36yvlDfoPPclWmWeyOfFEp9lVhQm0WhfDK7GiuRtaOxD-tOvpTjpcoZBeJb7bSg2OsneyeM_33a0WoPmjHw8WIxbroJz_PrfE72_TzbcTSDttKAv_e75PE48Vvx0661miFv4Gq8RBzMl2G3pQMEVCOm83v7BpodfN_YVJcqZJjVHMA70TZQ4K3L4_i9sIK9jJFfwEDVM7nsDnUu96n4vKs1fVvAuieCIPAJrfNOUMy7TwLvhnhUARsKnzmtNNrJuDhhBx-X93AHcG3micXgnqkFdKn6-ZUZ63I2KEdmjwKmLTRrv4n4eZKrRN-OrHPI4gLxJUhmyPAHzZrikMVBcDYfALqyki5SeKkwd4v0JAm87QzR4YwMdKErr0Xa5JrZqHGe2TZgVO4hIc-KrPw"; - - // token without kid, issuer = "me" and audience = "some" - pub const JWT_VALID_TOKEN_NO_KID: &str = "eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjIwMTkwNTY0NDEsImlzcyI6Im1lIiwiYXVkIjoic29tZSJ9.E_3s1MCdyRPDvpTtM4woHmSrRxU3_zRMSIbGSQYe3zyRQ-d2Tw6jVVleZ39GJ88l3yw0pGrrkdGkRBi1lammrUryoe0Sp8_FQ-tZ1jrkCV3qd75n3X_WYnG8CRiPaDZX5VDEFlF30h1x3gyEBpDloOa657AYqwG20XTG5xgicvOGY7SGsyO6IwNWXbbiJnH5cStNPb5mQ97cY8QDKryT5InWHWMO1USByqUYoj-AL4HdIrr5HUaZqDIJEberLddIIHW446pd55PhW6PXS9voLmJv9in9ckCTij_AVOdr7shDlQqZhfIZAVYFSqG64Vs4GM1jEwHVoP_EK-4L7nq3TQ"; - - pub static JWK_SET: Lazy = Lazy::new(|| { - let value = serde_json::json!({ - "keys": [ - { - "kty": "RSA", - "use": "sig", - "alg": "RS256", - "kid": "I48qMJp566SSKQogYXYtHBo9q6ZcEKHixNPeNoxV1c8", - "n": "ksMb5oMlhJ_HzAebCuBG6-v5Qc4J111ur7Aux6-8SbxzqFONsf2Bw6ATG8pAfNeZ-USA3_T1mGkYTDvfoggXnxsduWV_lePZKKOq_Qp_EDdzic1bVTJQDad3CXldR3wV6UFDtMx6cCLXxPZM5n76e7ybPt0iNgwoGpJE28emMZJXrnEUFzxwFMq61UlzWEumYqW3uOUVp7r5XAF5jQ_1nQAnpHBnRFzdNPVb3E6odMGu3jgp8mkPbPMP16Fund4LVplLz8yrsE9TdVrSdYJThylRWn_BwvJ0DjUcp8ibJya86iClUlixAmBwR9NdStHwQqHwmMXMKkTXo-ytRmSUobzxX9T8ESkij6iBhQpmDMD3FbkK30Y7pUVEBBOyDfNcWOhholjOj9CRrxu9to5rc2wvufe24VlbKb9wngS_uGfK4AYvVyrcjdYMFkdqw-Mft14HwzdO2BTS0TeMDZuLmYhj_bu5_g2Zu6PH5OpIXF6Fi8_679pCG8wWAcFQrFrM0eA70wD_SqD_BXn6pWRpFXlcRy_7PWTZ3QmC7ycQFR6Wc6Px44y1xDUoq3rH0RlZkeicfvP6FRlpjFU7xF6LjAfd9ciYBZfJll6PE7zf-i_ZXEslv-tJ5-30-I4Slwj0tDrZ2Z54OgAg07AIwAiI5o4y-0vmuhUscNpfZsGAGhE", - "e": "AQAB" - }, - { - "kty": "RSA", - "n": "u1SU1LfVLPHCozMxH2Mo4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0_IzW7yWR7QkrmBL7jTKEn5u-qKhbwKfBstIs-bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyehkd3qqGElvW_VDL5AaWTg0nLVkjRo9z-40RQzuVaE8AkAFmxZzow3x-VJYKdjykkJ0iT9wCS0DRTXu269V264Vf_3jvredZiKRkgwlL9xNAwxXFg0x_XFw005UWVRIkdgcKWTjpBP2dPwVZ4WWC-9aGVd-Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbcmw", - "e": "AQAB", - "alg": "RS256" - } - ] - }); - - serde_json::from_value(value).unwrap() - }); - - impl blueprint::JwtProvider { - pub fn test_value() -> Self { - let jwks = blueprint::Jwks::Local(JWK_SET.clone()); - - Self { issuer: Default::default(), audiences: Default::default(), optional_kid: false, jwks } - } - } - - pub fn create_jwt_auth_request(token: &str) -> RequestContext { - let mut req_context = RequestContext::default(); - - req_context - .req_headers - .typed_insert(Authorization::bearer(token).unwrap()); - - req_context - } - - #[tokio::test] - async fn validate_token_iss() { - let jwt_options = blueprint::JwtProvider::test_value(); - let jwt_provider = JwtVerifier::new(jwt_options, Arc::new(MockHttpClient)); - - let valid = jwt_provider - .verify(&create_jwt_auth_request(JWT_VALID_TOKEN_WITH_KID)) - .await; - - assert!(valid.is_ok()); - - let jwt_options = blueprint::JwtProvider { issuer: Some("me".to_owned()), ..blueprint::JwtProvider::test_value() }; - let jwt_provider = JwtVerifier::new(jwt_options, Arc::new(MockHttpClient)); - - let valid = jwt_provider - .verify(&create_jwt_auth_request(JWT_VALID_TOKEN_WITH_KID)) - .await; - - assert!(valid.is_ok()); - - let jwt_options = - blueprint::JwtProvider { issuer: Some("another".to_owned()), ..blueprint::JwtProvider::test_value() }; - let jwt_provider = JwtVerifier::new(jwt_options, Arc::new(MockHttpClient)); - - let error = jwt_provider - .verify(&create_jwt_auth_request(JWT_VALID_TOKEN_WITH_KID)) - .await - .err(); - - assert_eq!(error, Some(Error::Invalid)); - } - - #[tokio::test] - async fn validate_token_aud() { - let jwt_options = blueprint::JwtProvider::test_value(); - let jwt_provider = JwtVerifier::new(jwt_options, Arc::new(MockHttpClient)); - - let valid = jwt_provider - .verify(&create_jwt_auth_request(JWT_VALID_TOKEN_WITH_KID)) - .await; - - assert!(valid.is_ok()); - - let jwt_options = blueprint::JwtProvider { - audiences: HashSet::from_iter(["them".to_string()]), - ..blueprint::JwtProvider::test_value() - }; - let jwt_provider = JwtVerifier::new(jwt_options, Arc::new(MockHttpClient)); - - let valid = jwt_provider - .verify(&create_jwt_auth_request(JWT_VALID_TOKEN_WITH_KID)) - .await; - - assert!(valid.is_ok()); - - let jwt_options = blueprint::JwtProvider { - audiences: HashSet::from_iter(["anothem".to_string()]), - ..blueprint::JwtProvider::test_value() - }; - let jwt_provider = JwtVerifier::new(jwt_options, Arc::new(MockHttpClient)); - - let error = jwt_provider - .verify(&create_jwt_auth_request(JWT_VALID_TOKEN_WITH_KID)) - .await - .err(); - - assert_eq!(error, Some(Error::Invalid)); - } - - mod iss { - use super::*; - use crate::blueprint::JwtProvider; - - #[test] - fn validate_iss_not_defined() { - let options = JwtProvider::test_value(); - let mut claims = JwtClaim::default(); - - assert!(validate_iss(&options, &claims)); - - claims.iss = Some("iss".to_owned()); - - assert!(validate_iss(&options, &claims)); - } - - #[test] - fn validate_iss_defined() { - let options = JwtProvider { issuer: Some("iss".to_owned()), ..JwtProvider::test_value() }; - let mut claims = JwtClaim::default(); - - assert!(!validate_iss(&options, &claims)); - - claims.iss = Some("wrong".to_owned()); - - assert!(!validate_iss(&options, &claims)); - - claims.iss = Some("iss".to_owned()); - - assert!(validate_iss(&options, &claims)); - } - } - - mod aud { - use std::collections::HashSet; - - use super::*; - use crate::blueprint::JwtProvider; - - #[test] - fn validate_aud_not_defined() { - let options = JwtProvider::test_value(); - let mut claims = JwtClaim::default(); - assert!(validate_aud(&options, &claims)); - - claims.aud = Some(OneOrMany::One("aud".to_owned())); - assert!(validate_aud(&options, &claims)); - - claims.aud = Some(OneOrMany::Vec(vec!["aud1".to_owned(), "aud2".to_owned()])); - assert!(validate_aud(&options, &claims)); - } - - #[test] - fn validate_aud_defined() { - let options = JwtProvider { - audiences: HashSet::from_iter(["aud1".to_owned(), "aud2".to_owned()]), - ..JwtProvider::test_value() - }; - let mut claims = JwtClaim::default(); - assert!(!validate_aud(&options, &claims)); - - claims.aud = Some(OneOrMany::One("wrong".to_owned())); - assert!(!validate_aud(&options, &claims)); - - claims.aud = Some(OneOrMany::One("aud1".to_owned())); - assert!(validate_aud(&options, &claims)); - - claims.aud = Some(OneOrMany::Vec(vec!["aud1".to_owned(), "aud5".to_owned()])); - assert!(validate_aud(&options, &claims)); - } - } -} diff --git a/src/auth/jwt/mod.rs b/src/auth/jwt/mod.rs deleted file mode 100644 index 713ca3dd80..0000000000 --- a/src/auth/jwt/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod jwks; -pub mod jwks_decoder; -pub mod jwks_remote; -pub mod jwt_verify; diff --git a/src/auth/mod.rs b/src/auth/mod.rs deleted file mode 100644 index 9422c237d6..0000000000 --- a/src/auth/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod basic; -pub mod context; -pub mod error; -pub mod jwt; -pub mod verify; diff --git a/src/auth/verify.rs b/src/auth/verify.rs deleted file mode 100644 index 9a47add12c..0000000000 --- a/src/auth/verify.rs +++ /dev/null @@ -1,38 +0,0 @@ -use std::sync::Arc; - -use super::basic::BasicVerifier; -use super::error::Error; -use super::jwt::jwt_verify::JwtVerifier; -use crate::http::RequestContext; -use crate::{blueprint, HttpIO}; - -pub(crate) trait Verify { - async fn verify(&self, req_ctx: &RequestContext) -> Result<(), Error>; -} - -#[allow(clippy::large_enum_variant)] -// The difference in size is indeed significant here -// but it's quite unlikely that someone will require to store several hundreds -// of providers or more to care much -pub enum AuthVerifier { - Basic(BasicVerifier), - Jwt(JwtVerifier), -} - -impl AuthVerifier { - pub fn from_config(config: blueprint::AuthProvider, client: Arc) -> Self { - match config { - blueprint::AuthProvider::Basic(options) => AuthVerifier::Basic(BasicVerifier::new(options)), - blueprint::AuthProvider::Jwt(options) => AuthVerifier::Jwt(JwtVerifier::new(options, client)), - } - } -} - -impl Verify for AuthVerifier { - async fn verify(&self, req_ctx: &RequestContext) -> Result<(), Error> { - match self { - AuthVerifier::Basic(basic) => basic.verify(req_ctx).await, - AuthVerifier::Jwt(jwt) => jwt.verify(req_ctx).await, - } - } -} diff --git a/src/blueprint/from_config/auth.rs b/src/blueprint/from_config/auth.rs deleted file mode 100644 index aa6716d769..0000000000 --- a/src/blueprint/from_config/auth.rs +++ /dev/null @@ -1,110 +0,0 @@ -use std::collections::HashSet; -use std::time::Duration; - -use jsonwebtoken::jwk::JwkSet; -use url::Url; - -use super::init_context::InitContext; -use crate::config; -use crate::directive::DirectiveCodec; -use crate::mustache::Mustache; -use crate::valid::{Valid, ValidationError}; - -#[derive(Debug, Clone)] -pub struct BasicProvider { - pub htpasswd: String, -} - -#[derive(Debug, Clone)] -pub enum Jwks { - Local(JwkSet), - Remote { url: Url, max_age: Duration }, -} - -#[derive(Clone, Debug)] -pub struct JwtProvider { - pub issuer: Option, - pub audiences: HashSet, - pub optional_kid: bool, - pub jwks: Jwks, -} - -#[derive(Clone, Debug)] -pub enum AuthProvider { - Basic(BasicProvider), - Jwt(JwtProvider), -} - -#[derive(Clone, Debug)] -pub struct AuthEntry { - pub provider: AuthProvider, -} - -#[derive(Clone, Default, Debug)] -pub struct Auth(pub Vec); - -impl Auth { - pub fn make(init_context: &InitContext, auth: &config::Auth) -> Valid { - Valid::from_iter(&auth.0, |input| { - let provider = match &input.provider { - config::AuthProvider::Basic(basic) => to_basic(init_context, basic.clone()) - .map(AuthProvider::Basic) - .trace(config::Basic::directive_name().as_str()), - config::AuthProvider::Jwt(jwt) => to_jwt(init_context, jwt.clone()) - .map(AuthProvider::Jwt) - .trace(config::Jwt::directive_name().as_str()), - }; - - provider.map(|provider| AuthEntry { provider }) - }) - .map(Auth) - .trace(config::Auth::directive_name().as_str()) - } -} - -fn to_basic(init_context: &InitContext, options: config::Basic) -> Valid { - match options { - config::Basic::Htpasswd(data) => { - Valid::from(Mustache::parse(&data).map_err(|e| ValidationError::new(e.to_string()))).map(|tmpl| { - let htpasswd = tmpl.render(init_context); - - BasicProvider { htpasswd } - }) - } - } -} - -fn to_jwt(init_context: &InitContext, options: config::Jwt) -> Valid { - let jwks = &options.jwks; - - let jwks_valid = match &jwks { - config::Jwks::Data(data) => Valid::from(Mustache::parse(data).map_err(|e| ValidationError::new(e.to_string()))) - .and_then(|tmpl| { - let data = tmpl.render(init_context); - - if data.is_empty() { - return Valid::fail("JWKS data is empty".into()); - } - - let de = &mut serde_json::Deserializer::from_str(&data); - - Valid::from(serde_path_to_error::deserialize(de).map_err(ValidationError::from)) - .map(|jwks: JwkSet| Jwks::Local(jwks)) - }), - config::Jwks::Remote { url, max_age } => { - Valid::from(Mustache::parse(url).map_err(|e| ValidationError::new(e.to_string()))).and_then(|url| { - let url = url.render(init_context); - - Valid::from(Url::parse(&url).map_err(|e| ValidationError::new(e.to_string()))) - .map(|url| Jwks::Remote { url, max_age: Duration::from_millis(max_age.get()) }) - }) - } - }; - - jwks_valid.map(|jwks| JwtProvider { - issuer: options.issuer, - audiences: options.audiences, - optional_kid: options.optional_kid, - jwks, - }) -} diff --git a/src/blueprint/from_config/definitions.rs b/src/blueprint/from_config/definitions.rs index 9533720c33..0184373928 100644 --- a/src/blueprint/from_config/definitions.rs +++ b/src/blueprint/from_config/definitions.rs @@ -351,7 +351,6 @@ fn to_fields(object_name: &str, type_of: &config::Type, config: &Config) -> Vali .and(update_expr(&operation_type).trace(config::Expr::trace_name().as_str())) .and(update_modify().trace(config::Modify::trace_name().as_str())) .and(update_nested_resolvers()) - .and(update_protected()) .try_fold(&(config, field, type_of, name), FieldDefinition::default()) }; diff --git a/src/blueprint/from_config/init_context.rs b/src/blueprint/from_config/init_context.rs deleted file mode 100644 index bf894ab7b3..0000000000 --- a/src/blueprint/from_config/init_context.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::borrow::Cow; -use std::collections::{BTreeMap, HashMap}; - -use crate::config; -use crate::path::PathString; - -#[derive(Debug)] -pub struct InitContext { - pub vars: BTreeMap, - pub env_vars: HashMap, -} - -impl InitContext { - pub fn env_var(&self, key: &str) -> Option<&str> { - self.env_vars.get(key).map(|v| v.as_str()) - } - - pub fn var(&self, key: &str) -> Option<&str> { - self.vars.get(key).map(|v| v.as_str()) - } -} - -impl From<&config::Server> for InitContext { - fn from(server: &config::Server) -> Self { - Self { vars: server.vars.clone().0, env_vars: std::env::vars().collect() } - } -} - -impl PathString for InitContext { - fn path_string>(&self, path: &[T]) -> Option> { - let ctx = self; - - if path.is_empty() { - return None; - } - - path.split_first().and_then(|(head, tail)| match head.as_ref() { - "vars" => ctx.var(tail[0].as_ref()).map(|v| v.into()), - "env" => ctx.env_var(tail[0].as_ref()).map(|v| v.into()), - _ => None, - }) - } -} diff --git a/src/blueprint/from_config/mod.rs b/src/blueprint/from_config/mod.rs index 99506829c0..b78f841ea2 100644 --- a/src/blueprint/from_config/mod.rs +++ b/src/blueprint/from_config/mod.rs @@ -1,13 +1,10 @@ -mod auth; mod definitions; mod from_config; -mod init_context; mod operators; mod schema; mod server; mod upstream; -pub use auth::*; pub use definitions::*; pub use from_config::*; pub use operators::*; diff --git a/src/blueprint/from_config/operators/mod.rs b/src/blueprint/from_config/operators/mod.rs index e1891d0e8c..85e3b234c4 100644 --- a/src/blueprint/from_config/operators/mod.rs +++ b/src/blueprint/from_config/operators/mod.rs @@ -5,7 +5,6 @@ mod grpc; mod http; mod js; mod modify; -mod protected; pub use const_field::*; pub use expr::*; @@ -14,4 +13,3 @@ pub use grpc::*; pub use http::*; pub use js::*; pub use modify::*; -pub use protected::*; diff --git a/src/blueprint/from_config/operators/protected.rs b/src/blueprint/from_config/operators/protected.rs deleted file mode 100644 index 6d03af2e5b..0000000000 --- a/src/blueprint/from_config/operators/protected.rs +++ /dev/null @@ -1,24 +0,0 @@ -use crate::blueprint::FieldDefinition; -use crate::config::{self, Config, Field, Protected}; -use crate::directive::DirectiveCodec; -use crate::lambda::Lambda; -use crate::try_fold::TryFold; -use crate::valid::Valid; - -pub fn update_protected<'a>() -> TryFold<'a, (&'a Config, &'a Field, &'a config::Type, &'a str), FieldDefinition, String> -{ - TryFold::<(&Config, &Field, &config::Type, &'a str), FieldDefinition, String>::new( - |(config, field, type_, _), b_field| { - Valid::succeed(if field.protected || type_.protected { - if !config.server.auth.is_some() { - return Valid::fail("@protected operator is used without defining auth @server".to_owned()) - .trace(Protected::trace_name().as_str()); - } - - b_field.resolver_or_default(Lambda::context().auth_protected(), |r| r.auth_protected()) - } else { - b_field - }) - }, - ) -} diff --git a/src/blueprint/from_config/server.rs b/src/blueprint/from_config/server.rs index d9d9d97c3b..d1012de98d 100644 --- a/src/blueprint/from_config/server.rs +++ b/src/blueprint/from_config/server.rs @@ -5,10 +5,7 @@ use derive_setters::Setters; use hyper::header::{HeaderName, HeaderValue}; use hyper::HeaderMap; -use super::init_context::InitContext; -use super::Auth; use crate::config::{self, HttpVersion}; -use crate::directive::DirectiveCodec; use crate::valid::{Valid, ValidationError}; #[derive(Clone, Debug, Setters)] @@ -28,7 +25,6 @@ pub struct Server { pub response_headers: HeaderMap, pub http: Http, pub pipeline_flush: bool, - pub auth: Auth, } #[derive(Clone, Debug)] @@ -61,7 +57,7 @@ impl Server { } } -impl TryFrom for Server { +impl TryFrom for Server { type Error = ValidationError; fn try_from(config_server: config::Server) -> Result { @@ -77,13 +73,11 @@ impl TryFrom for Server { } _ => Valid::succeed(Http::HTTP1), }; - let init_context = InitContext::from(&config_server); validate_hostname((config_server).get_hostname().to_lowercase()) .zip(http_server) .zip(handle_response_headers((config_server).get_response_headers().0)) - .zip(Auth::make(&init_context, &config_server.auth)) - .map(|(((hostname, http), response_headers), auth)| Server { + .map(|((hostname, http), response_headers)| Server { enable_apollo_tracing: (config_server).enable_apollo_tracing(), enable_cache_control_header: (config_server).enable_cache_control(), enable_graphiql: (config_server).enable_graphiql(), @@ -99,10 +93,7 @@ impl TryFrom for Server { vars: (config_server).get_vars(), pipeline_flush: (config_server).get_pipeline_flush(), response_headers, - auth, }) - .trace(config::Server::trace_name().as_str()) - .trace("schema") .to_result() } } @@ -117,6 +108,8 @@ fn validate_hostname(hostname: String) -> Valid { .map_err(|e: AddrParseError| ValidationError::new(format!("Parsing failed because of {}", e))), ) .trace("hostname") + .trace("@server") + .trace("schema") } } @@ -133,6 +126,8 @@ fn handle_response_headers(resp_headers: BTreeMap) -> Valid()) .trace("responseHeaders") + .trace("@server") + .trace("schema") } #[cfg(test)] diff --git a/src/config/auth.rs b/src/config/auth.rs deleted file mode 100644 index 48a9afb8cb..0000000000 --- a/src/config/auth.rs +++ /dev/null @@ -1,107 +0,0 @@ -use std::collections::HashSet; -use std::num::NonZeroU64; - -use serde::{Deserialize, Serialize}; - -use super::is_default; - -mod default { - pub mod jwt { - pub mod remote { - use std::num::NonZeroU64; - - pub fn max_age() -> NonZeroU64 { - NonZeroU64::new(5 * 60 * 1000).unwrap() - } - } - } -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, schemars::JsonSchema)] -#[serde(rename_all = "camelCase")] -pub enum Basic { - Htpasswd(String), -} - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, schemars::JsonSchema)] -#[serde(rename_all = "camelCase")] -pub enum Jwks { - Data(String), - #[serde(rename_all = "camelCase")] - Remote { - url: String, - #[serde(default = "default::jwt::remote::max_age")] - max_age: NonZeroU64, - }, -} - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, schemars::JsonSchema)] -#[serde(rename_all = "camelCase")] -pub struct Jwt { - #[serde(skip_serializing_if = "is_default")] - pub issuer: Option, - #[serde(default, skip_serializing_if = "is_default")] - pub audiences: HashSet, - #[serde(default, skip_serializing_if = "is_default")] - pub optional_kid: bool, - pub jwks: Jwks, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, schemars::JsonSchema)] -#[serde(rename_all = "camelCase")] -pub enum AuthProvider { - Jwt(Jwt), - Basic(Basic), -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, schemars::JsonSchema)] -pub struct AuthEntry { - pub id: Option, - #[serde(flatten)] - pub provider: AuthProvider, -} - -#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq, schemars::JsonSchema)] -pub struct Auth(pub Vec); - -impl Auth { - pub fn merge_right(self, other: Auth) -> Self { - let mut providers = self.0; - - providers.extend(other.0); - - Self(providers) - } - - pub fn is_some(&self) -> bool { - !self.0.is_empty() - } -} - -#[cfg(test)] -mod tests { - - use anyhow::Result; - use serde_json::json; - - use super::*; - - #[test] - fn jwt_options_parse() -> Result<()> { - let config: Jwt = serde_json::from_value(json!({ - "optionalKid": true, - "jwks": { - "remote": { - "url": "http://localhost:3000" - } - } - }))?; - - assert!(matches!( - config, - Jwt { optional_kid: true, jwks: Jwks::Remote { .. }, .. } - )); - - Ok(()) - } -} diff --git a/src/config/config.rs b/src/config/config.rs index b8a008c569..251fb61d20 100644 --- a/src/config/config.rs +++ b/src/config/config.rs @@ -211,8 +211,6 @@ pub struct Type { /// Setting to indicate if the type is cacheable. /// pub cache: Option, - #[serde(default)] - pub protected: bool, } impl Type { @@ -247,9 +245,6 @@ pub struct Cache { pub max_age: NonZeroU64, } -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] -pub struct Protected {} - fn merge_types(mut self_types: BTreeMap, other_types: BTreeMap) -> BTreeMap { for (name, mut other_type) in other_types { if let Some(self_type) = self_types.remove(&name) { @@ -391,8 +386,6 @@ pub struct Field { /// Sets the cache configuration for a field /// pub cache: Option, - #[serde(default)] - pub protected: bool, } impl Field { diff --git a/src/config/from_document.rs b/src/config/from_document.rs index 246a101344..c3eea04928 100644 --- a/src/config/from_document.rs +++ b/src/config/from_document.rs @@ -8,9 +8,7 @@ use async_graphql::parser::Positioned; use async_graphql::Name; use super::JS; -use crate::config::{ - self, Cache, Config, Expr, GraphQL, Grpc, Modify, Omit, Protected, RootSchema, Server, Union, Upstream, -}; +use crate::config::{self, Cache, Config, Expr, GraphQL, Grpc, Modify, Omit, RootSchema, Server, Union, Upstream}; use crate::directive::DirectiveCodec; use crate::valid::Valid; @@ -63,11 +61,9 @@ fn process_schema_directives + Default>( fn server(schema_definition: &SchemaDefinition) -> Valid { process_schema_directives(schema_definition, config::Server::directive_name().as_str()) } - fn upstream(schema_definition: &SchemaDefinition) -> Valid { process_schema_directives(schema_definition, config::Upstream::directive_name().as_str()) } - fn to_root_schema(schema_definition: &SchemaDefinition) -> RootSchema { let query = schema_definition.query.as_ref().map(pos_name_to_string); let mutation = schema_definition.mutation.as_ref().map(pos_name_to_string); @@ -147,22 +143,12 @@ where let implements = object.implements(); let interface = object.is_interface(); - to_fields(fields, cache) - .zip(Protected::from_directives(directives.iter())) - .map(|(fields, protected)| { - let doc = description.to_owned().map(|pos| pos.node); - let implements = implements.iter().map(|pos| pos.node.to_string()).collect(); - let added_fields = to_add_fields_from_directives(directives); - config::Type { - fields, - added_fields, - doc, - interface, - implements, - protected: protected.is_some(), - ..Default::default() - } - }) + to_fields(fields, cache).map(|fields| { + let doc = description.to_owned().map(|pos| pos.node); + let implements = implements.iter().map(|pos| pos.node.to_string()).collect(); + let added_fields = to_add_fields_from_directives(directives); + config::Type { fields, added_fields, doc, interface, implements, ..Default::default() } + }) } fn to_enum(enum_type: EnumType) -> config::Type { let variants = enum_type @@ -237,31 +223,27 @@ where .zip(Expr::from_directives(directives.iter())) .zip(Omit::from_directives(directives.iter())) .zip(Modify::from_directives(directives.iter())) - .zip(Protected::from_directives(directives.iter())) .zip(JS::from_directives(directives.iter())) - .map( - |((((((((http, graphql), cache), grpc), expr), omit), modify), protected), script)| { - let const_field = to_const_field(directives); - config::Field { - type_of, - list, - required: !nullable, - list_type_required, - args, - doc, - modify, - omit, - http, - grpc, - script, - const_field, - graphql, - expr, - cache: cache.or(parent_cache), - protected: protected.is_some(), - } - }, - ) + .map(|(((((((http, graphql), cache), grpc), expr), omit), modify), script)| { + let const_field = to_const_field(directives); + config::Field { + type_of, + list, + required: !nullable, + list_type_required, + args, + doc, + modify, + omit, + http, + grpc, + script, + const_field, + graphql, + expr, + cache: cache.or(parent_cache), + } + }) } fn to_type_of(type_: &Type) -> String { diff --git a/src/config/into_document.rs b/src/config/into_document.rs index a3f041bcc6..3545d43e82 100644 --- a/src/config/into_document.rs +++ b/src/config/into_document.rs @@ -2,7 +2,7 @@ use async_graphql::parser::types::*; use async_graphql::{Pos, Positioned}; use async_graphql_value::{ConstValue, Name}; -use super::{Config, Protected}; +use super::Config; use crate::blueprint::TypeLike; use crate::directive::DirectiveCodec; @@ -11,11 +11,9 @@ fn pos(a: A) -> Positioned { } fn config_document(config: &Config) -> ServiceDocument { let mut definitions = Vec::new(); - let directives = vec![pos(config.server.to_directive()), pos(config.upstream.to_directive())]; - let schema_definition = SchemaDefinition { extend: false, - directives, + directives: vec![pos(config.server.to_directive()), pos(config.upstream.to_directive())], query: config.schema.query.clone().map(|name| pos(Name::new(name))), mutation: config.schema.mutation.clone().map(|name| pos(Name::new(name))), subscription: config.schema.subscription.clone().map(|name| pos(Name::new(name))), @@ -190,11 +188,6 @@ fn get_directives(field: &crate::config::Field) -> Vec, #[serde(default, skip_serializing_if = "is_default")] pub pipeline_flush: Option, - #[serde(default, skip_serializing_if = "is_default")] - pub auth: Auth, } #[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone, Default, schemars::JsonSchema)] @@ -162,7 +159,6 @@ impl Server { self.cert = other.cert.or(self.cert); self.key = other.key.or(self.key); self.pipeline_flush = other.pipeline_flush.or(self.pipeline_flush); - self.auth = self.auth.merge_right(other.auth); self } } diff --git a/src/grpc/protobuf.rs b/src/grpc/protobuf.rs index a7198699b5..b586be657e 100644 --- a/src/grpc/protobuf.rs +++ b/src/grpc/protobuf.rs @@ -1,5 +1,6 @@ +use std::env::current_dir; use std::fmt::Debug; -use std::path::Path; +use std::path::{Path, PathBuf}; use anyhow::{anyhow, bail, Context, Result}; use async_graphql::Value; @@ -8,8 +9,6 @@ use prost::Message; use prost_reflect::{DescriptorPool, DynamicMessage, MessageDescriptor, MethodDescriptor, ServiceDescriptor}; use serde_json::Deserializer; -use crate::helpers::config_path::config_path; - fn to_message(descriptor: &MessageDescriptor, input: &str) -> Result { let mut deserializer = Deserializer::from_str(input); let message = DynamicMessage::deserialize(descriptor.clone(), &mut deserializer) @@ -66,7 +65,13 @@ impl ProtobufSet { // it could be more convenient to load FileDescriptorSet instead // either from file or server reflection pub fn from_proto_file(proto_path: &Path) -> Result { - let proto_path = config_path(proto_path)?; + let proto_path = if proto_path.is_relative() { + let dir = current_dir()?; + + dir.join(proto_path) + } else { + PathBuf::from(proto_path) + }; let parent_dir = proto_path .parent() diff --git a/src/helpers/config_path.rs b/src/helpers/config_path.rs deleted file mode 100644 index 6cd7211ad2..0000000000 --- a/src/helpers/config_path.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::env::current_dir; -use std::path::{Path, PathBuf}; - -pub fn config_path(path: &Path) -> Result { - let path = if path.is_relative() { - let dir = current_dir()?; - - dir.join(path) - } else { - PathBuf::from(path) - }; - - Ok(path) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn relative_path() -> anyhow::Result<()> { - let cwd = current_dir()?; - - assert_eq!(config_path(Path::new("tests/path.json"))?, cwd.join("tests/path.json")); - assert_eq!( - config_path(Path::new("./tests/path.json"))?, - cwd.join("tests/path.json") - ); - - Ok(()) - } - - #[test] - fn absolute_path() -> anyhow::Result<()> { - assert_eq!( - config_path(Path::new("/tests/path.json"))?, - PathBuf::from(Path::new("/tests/path.json")) - ); - - Ok(()) - } -} diff --git a/src/helpers/mod.rs b/src/helpers/mod.rs index 6dc4d7e779..1d82ddf4a8 100644 --- a/src/helpers/mod.rs +++ b/src/helpers/mod.rs @@ -1,5 +1,4 @@ pub mod body; -pub mod config_path; pub mod headers; pub mod url; pub mod value; diff --git a/src/http/data_loader.rs b/src/http/data_loader.rs index b6939ddf83..8940778eb2 100644 --- a/src/http/data_loader.rs +++ b/src/http/data_loader.rs @@ -79,7 +79,7 @@ impl Loader for HttpDataLoader { first_url.query_pairs_mut().extend_pairs(url.query_pairs()); } - let res = self.client.execute(request).await?.to_json::()?; + let res = self.client.execute(request).await?.to_json()?; #[allow(clippy::mutable_key_type)] let mut hashmap = HashMap::with_capacity(keys.len()); let path = &group_by.path(); diff --git a/src/http/request_context.rs b/src/http/request_context.rs index 0c6ca31165..e3b0f52914 100644 --- a/src/http/request_context.rs +++ b/src/http/request_context.rs @@ -6,7 +6,6 @@ use cache_control::{Cachability, CacheControl}; use derive_setters::Setters; use hyper::HeaderMap; -use crate::auth::context::AuthContext; use crate::blueprint::Server; use crate::chrono_cache::ChronoCache; use crate::config::Upstream; @@ -27,16 +26,13 @@ pub struct RequestContext { pub server: Server, pub upstream: Upstream, pub req_headers: HeaderMap, - // request headers from client that will be sent to upstream - pub allowed_headers: HeaderMap, - pub auth_ctx: AuthContext, pub http_data_loaders: Arc>>, pub gql_data_loaders: Arc>>, + pub cache: ChronoCache, pub grpc_data_loaders: Arc>>, pub min_max_age: Arc>>, pub cache_public: Arc>>, pub env_vars: Arc, - pub cache: ChronoCache, } impl RequestContext { @@ -106,12 +102,10 @@ impl From<&AppContext> for RequestContext { server: server_ctx.blueprint.server.clone(), upstream: server_ctx.blueprint.upstream.clone(), req_headers: HeaderMap::new(), - allowed_headers: HeaderMap::new(), - auth_ctx: (&server_ctx.auth_ctx).into(), http_data_loaders: server_ctx.http_data_loaders.clone(), gql_data_loaders: server_ctx.gql_data_loaders.clone(), - grpc_data_loaders: server_ctx.grpc_data_loaders.clone(), cache: server_ctx.cache.clone(), + grpc_data_loaders: server_ctx.grpc_data_loaders.clone(), min_max_age: Arc::new(Mutex::new(None)), cache_public: Arc::new(Mutex::new(None)), env_vars: server_ctx.env_vars.clone(), @@ -126,7 +120,6 @@ mod test { use cache_control::Cachability; use hyper::HeaderMap; - use crate::auth::context::AuthContext; use crate::blueprint::Server; use crate::chrono_cache::ChronoCache; use crate::cli::{init_env, init_http, init_http2_only}; @@ -136,13 +129,13 @@ mod test { impl Default for RequestContext { fn default() -> Self { let crate::config::Config { server, upstream, .. } = crate::config::Config::default(); + //TODO: default is used only in tests. Drop default and move it to test. let server = Server::try_from(server).unwrap(); let h_client = Arc::new(init_http(&upstream)); let h2_client = Arc::new(init_http2_only(&upstream.clone())); RequestContext { req_headers: HeaderMap::new(), - allowed_headers: HeaderMap::new(), h_client, h2_client, server, @@ -154,7 +147,6 @@ mod test { min_max_age: Arc::new(Mutex::new(None)), cache_public: Arc::new(Mutex::new(None)), env_vars: Arc::new(init_env()), - auth_ctx: AuthContext::default(), } } } diff --git a/src/http/request_handler.rs b/src/http/request_handler.rs index a40f33f023..fec0d88467 100644 --- a/src/http/request_handler.rs +++ b/src/http/request_handler.rs @@ -32,9 +32,7 @@ fn create_request_context( let upstream = server_ctx.blueprint.upstream.clone(); let allowed = upstream.get_allowed_headers(); let headers = create_allowed_headers(req.headers(), &allowed); - RequestContext::from(server_ctx) - .req_headers(req.headers().clone()) - .allowed_headers(headers) + RequestContext::from(server_ctx).req_headers(headers) } fn update_cache_control_header( diff --git a/src/http/response.rs b/src/http/response.rs index 43a84fdf68..6e1cb8e540 100644 --- a/src/http/response.rs +++ b/src/http/response.rs @@ -1,12 +1,11 @@ use anyhow::Result; use derive_setters::Setters; use hyper::body::Bytes; -use serde::de::DeserializeOwned; use crate::grpc::protobuf::ProtobufOperation; #[derive(Clone, Debug, Default, Setters)] -pub struct Response { +pub struct Response { pub status: reqwest::StatusCode, pub headers: reqwest::header::HeaderMap, pub body: Body, @@ -19,14 +18,17 @@ impl Response { let body = resp.bytes().await?; Ok(Response { status, headers, body }) } - pub fn empty() -> Self { Response { status: reqwest::StatusCode::OK, headers: reqwest::header::HeaderMap::default(), body: Bytes::new() } } - pub fn to_json(self) -> Result> { - let body = serde_json::from_slice::(&self.body)?; - Ok(Response { status: self.status, headers: self.headers, body }) + pub fn to_json(self) -> Result> { + let mut resp = Response::default(); + let body = serde_json::from_slice::(&self.body)?; + resp.body = body; + resp.status = self.status; + resp.headers = self.headers; + Ok(resp) } pub fn to_grpc_value(self, operation: &ProtobufOperation) -> Result> { diff --git a/src/lambda/evaluation_context.rs b/src/lambda/evaluation_context.rs index e1bdd40411..b84fe687ba 100644 --- a/src/lambda/evaluation_context.rs +++ b/src/lambda/evaluation_context.rs @@ -40,7 +40,7 @@ impl<'a, Ctx: ResolverContextLike<'a>> EvaluationContext<'a, Ctx> { } pub fn headers(&self) -> &HeaderMap { - &self.req_ctx.allowed_headers + &self.req_ctx.req_headers } pub fn header(&self, key: &str) -> Option<&str> { diff --git a/src/lambda/expression.rs b/src/lambda/expression.rs index 2bd959e0be..d9948241f6 100644 --- a/src/lambda/expression.rs +++ b/src/lambda/expression.rs @@ -24,7 +24,6 @@ pub enum Expression { List(List), Math(Math), Concurrency(Concurrent, Box), - Protected(Box), } #[derive(Clone, Debug)] @@ -97,10 +96,6 @@ impl Eval for Expression { Expression::EqualTo(left, right) => Ok(async_graphql::Value::from( left.eval(ctx, conc).await? == right.eval(ctx, conc).await?, )), - Expression::Protected(expr) => { - ctx.req_ctx.auth_ctx.validate(ctx.req_ctx).await?; - expr.eval(ctx, conc).await - } Expression::IO(operation) => operation.eval(ctx, conc).await, Expression::Relation(relation) => relation.eval(ctx, conc).await, diff --git a/src/lambda/lambda.rs b/src/lambda/lambda.rs index 01a095374e..fbcf9277c5 100644 --- a/src/lambda/lambda.rs +++ b/src/lambda/lambda.rs @@ -29,10 +29,6 @@ impl Lambda { pub fn to_input_path(self, path: Vec) -> Lambda { Lambda::new(Expression::Input(self.box_expr(), path)) } - - pub fn auth_protected(self) -> Lambda { - Lambda::new(Expression::Protected(self.box_expr())) - } } impl Lambda { diff --git a/src/lib.rs b/src/lib.rs index 3628703838..2f082538f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,6 @@ #![allow(clippy::mutable_key_type)] mod app_context; pub mod async_graphql_hyper; -pub mod auth; pub mod blueprint; pub mod cache; pub mod chrono_cache; diff --git a/src/path.rs b/src/path.rs index 699a0f10e9..6db0f19264 100644 --- a/src/path.rs +++ b/src/path.rs @@ -198,7 +198,7 @@ mod tests { } static REQ_CTX: Lazy = Lazy::new(|| { - let mut req_ctx = RequestContext::default().allowed_headers(TEST_HEADERS.clone()); + let mut req_ctx = RequestContext::default().req_headers(TEST_HEADERS.clone()); req_ctx.server.vars = TEST_VARS.clone(); req_ctx.env_vars = Arc::new(Env::init(TEST_ENV_VARS.clone())); diff --git a/src/valid/valid.rs b/src/valid/valid.rs index bb505c4bad..5816494270 100644 --- a/src/valid/valid.rs +++ b/src/valid/valid.rs @@ -153,16 +153,6 @@ impl From>> for Valid { } } -impl Clone for Valid -where - A: Clone, - E: Clone, -{ - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} - #[cfg(test)] mod tests { use super::{Cause, ValidationError}; diff --git a/tests/graphql/auth.graphql b/tests/graphql/auth.graphql deleted file mode 100644 index 18ea0244cd..0000000000 --- a/tests/graphql/auth.graphql +++ /dev/null @@ -1,17 +0,0 @@ -#> server-sdl -schema @server(auth: [{basic: {htpasswd: "{{env.BASIC_AUTH}}"}, id: "basic"}, {id: "jwt", jwt: {jwks: {data: "{{vars.JWKS}}"}}}], vars: [{key: "JWKS", value: "{\"keys\": []}"}]) @upstream { - query: Query -} - -type Query { - data: String @const(data: "data") @protected -} - -#> client-sdl -type Query { - data: String -} - -schema { - query: Query -} diff --git a/tests/graphql/errors/auth-protected-without-auth.graphql b/tests/graphql/errors/auth-protected-without-auth.graphql deleted file mode 100644 index 1c69d1fde9..0000000000 --- a/tests/graphql/errors/auth-protected-without-auth.graphql +++ /dev/null @@ -1,12 +0,0 @@ -#> server-sdl -schema { - query: Query -} - -type Query { - data: String @const(data: "data") @protected -} - -#> client-sdl -type Failure - @error(message: "@protected operator is used without defining auth @server", trace: ["Query", "data", "@protected"]) diff --git a/tests/graphql_spec.rs b/tests/graphql_spec.rs index e1e59d66f3..4508a296e3 100644 --- a/tests/graphql_spec.rs +++ b/tests/graphql_spec.rs @@ -4,7 +4,6 @@ use std::fs; use std::path::PathBuf; use std::sync::{Arc, Once}; -use anyhow::Context; use async_graphql::parser::types::TypeSystemDefinition; use async_graphql::Request; use derive_setters::Setters; @@ -260,30 +259,24 @@ fn test_config_identity() -> std::io::Result<()> { // Check server SDL matches expected client SDL #[test] -fn test_server_to_client_sdl() -> anyhow::Result<()> { +fn test_server_to_client_sdl() -> std::io::Result<()> { let specs = GraphQLSpec::cargo_read("tests/graphql"); for spec in specs? { - let display_path = spec.path.display(); let expected = spec.find_source(Tag::ClientSDL); let expected = expected.as_str(); let content = spec.find_source(Tag::ServerSDL); let content = content.as_str(); - let config = Config::from_sdl(content) - .to_result() - .with_context(|| format!("config creation failed for file {}", display_path))?; - let actual = print_schema::print_schema( - (Blueprint::try_from(&config).with_context(|| format!("blueprint creation failed for file {}", display_path))?) - .to_schema(), - ); + let config = Config::from_sdl(content).to_result().unwrap(); + let actual = print_schema::print_schema((Blueprint::try_from(&config).unwrap()).to_schema()); if spec.annotation.as_ref().is_some_and(|a| matches!(a, Annotation::Fail)) { - assert_ne!(actual, expected, "ClientSDL: {}", display_path); + assert_ne!(actual, expected, "ClientSDL: {}", spec.path.display()); } else { - assert_eq!(actual, expected, "ClientSDL: {}", display_path); + assert_eq!(actual, expected, "ClientSDL: {}", spec.path.display()); } - log::info!("ClientSDL: {} ... ok", display_path); + log::info!("ClientSDL: {} ... ok", spec.path.display()); } Ok(()) @@ -315,7 +308,7 @@ async fn test_execution() -> std::io::Result<()> { for q in spec.test_queries { let mut headers = HeaderMap::new(); headers.insert(HeaderName::from_static("authorization"), HeaderValue::from_static("1")); - let req_ctx = Arc::new(RequestContext::from(&server_ctx).allowed_headers(headers)); + let req_ctx = Arc::new(RequestContext::from(&server_ctx).req_headers(headers)); let req = Request::from(q.query.as_str()).data(req_ctx.clone()); let res = schema.execute(req).await; let json = serde_json::to_string(&res).unwrap(); diff --git a/tests/http/auth-basic-const-env.yml b/tests/http/auth-basic-const-env.yml deleted file mode 100644 index 356d8d038b..0000000000 --- a/tests/http/auth-basic-const-env.yml +++ /dev/null @@ -1,92 +0,0 @@ -config: !file tests/http/config/auth-basic-const-env.graphql -name: Auth with BasicAuth loaded from const env - -env: - HTPASSWD_CONTENT: | - testuser1:$apr1$e3dp9qh2$fFIfHU9bilvVZBl8TxKzL/ - testuser2:$2y$10$wJ/mZDURcAOBIrswCAKFsO0Nk7BpHmWl/XuhF7lNm3gBAFH3ofsuu - testuser3:{SHA}Y2fEjdGT1W6nsLqtJbGUVeUp9e4= - -assert: - - request: - method: POST - url: http://localhost:8080/graphql - body: - query: | - query { - scalar - nested { - name - } - } - response: - body: - data: - scalar: data from public scalar - nested: - name: protected nested name - - - request: - method: POST - url: http://localhost:8080/graphql - body: - query: | - query { - protectedScalar - } - response: - body: - data: null - errors: - - message: Haven't found auth parameters - locations: - - column: 3 - line: 2 - - - request: - method: POST - url: http://localhost:8080/graphql - headers: - Authorization: Basic dGVzdHVzZXIxOnJhbmRvbV9wYXNzd29yZA== # wrong password - body: - query: | - query { - protectedScalar - } - response: - body: - data: null - errors: - - message: Auth validation failed - locations: - - column: 3 - line: 2 - - - request: - method: POST - url: http://localhost:8080/graphql - headers: - Authorization: Basic dGVzdHVzZXIxOnBhc3N3b3JkMTIz - body: - query: | - query { - protectedScalar - nested { - name - protected - } - protectedType { - name - nested - } - } - response: - body: - data: - protectedScalar: data from protected scalar - nested: - name: protected nested name - protected: protected nested - protectedType: - name: protected type name - nested: protected type nested diff --git a/tests/http/auth-jwt-const-env.yml b/tests/http/auth-jwt-const-env.yml deleted file mode 100644 index b70c13afcc..0000000000 --- a/tests/http/auth-jwt-const-env.yml +++ /dev/null @@ -1,82 +0,0 @@ -config: !file tests/http/config/auth-jwt-const-env.graphql -name: Auth with JWT loaded from const env - -env: - JWKS: | - { - "keys": [ - { - "kty": "RSA", - "use": "sig", - "alg": "RS256", - "kid": "I48qMJp566SSKQogYXYtHBo9q6ZcEKHixNPeNoxV1c8", - "n": "ksMb5oMlhJ_HzAebCuBG6-v5Qc4J111ur7Aux6-8SbxzqFONsf2Bw6ATG8pAfNeZ-USA3_T1mGkYTDvfoggXnxsduWV_lePZKKOq_Qp_EDdzic1bVTJQDad3CXldR3wV6UFDtMx6cCLXxPZM5n76e7ybPt0iNgwoGpJE28emMZJXrnEUFzxwFMq61UlzWEumYqW3uOUVp7r5XAF5jQ_1nQAnpHBnRFzdNPVb3E6odMGu3jgp8mkPbPMP16Fund4LVplLz8yrsE9TdVrSdYJThylRWn_BwvJ0DjUcp8ibJya86iClUlixAmBwR9NdStHwQqHwmMXMKkTXo-ytRmSUobzxX9T8ESkij6iBhQpmDMD3FbkK30Y7pUVEBBOyDfNcWOhholjOj9CRrxu9to5rc2wvufe24VlbKb9wngS_uGfK4AYvVyrcjdYMFkdqw-Mft14HwzdO2BTS0TeMDZuLmYhj_bu5_g2Zu6PH5OpIXF6Fi8_679pCG8wWAcFQrFrM0eA70wD_SqD_BXn6pWRpFXlcRy_7PWTZ3QmC7ycQFR6Wc6Px44y1xDUoq3rH0RlZkeicfvP6FRlpjFU7xF6LjAfd9ciYBZfJll6PE7zf-i_ZXEslv-tJ5-30-I4Slwj0tDrZ2Z54OgAg07AIwAiI5o4y-0vmuhUscNpfZsGAGhE", - "e": "AQAB" - } - ] - } - -assert: - - request: - method: POST - url: http://localhost:8080/graphql - body: - query: | - query { - scalar - nested { - name - } - } - response: - body: - data: - scalar: data from public scalar - nested: - name: protected nested name - - - request: - method: POST - url: http://localhost:8080/graphql - body: - query: | - query { - protectedScalar - } - response: - body: - data: null - errors: - - message: Haven't found auth parameters - locations: - - column: 3 - line: 2 - - - request: - method: POST - url: http://localhost:8080/graphql - headers: - Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Ikk0OHFNSnA1NjZTU0tRb2dZWFl0SEJvOXE2WmNFS0hpeE5QZU5veFYxYzgifQ.eyJleHAiOjIwMTkwNTY0NDEuMCwiaXNzIjoibWUiLCJzdWIiOiJ5b3UiLCJhdWQiOlsidGhlbSJdfQ.cU-hJgVGWxK3-IBggYBChhf3FzibBKjuDLtq2urJ99FVXIGZls0VMXjyNW7yHhLLuif_9t2N5UIUIq-hwXVv7rrGRPCGrlqKU0jsUH251Spy7_ppG5_B2LsG3cBJcwkD4AVz8qjT3AaE_vYZ4WnH-CQ-F5Vm7wiYZgbdyU8xgKoH85KAxaCdJJlYOi8mApE9_zcdmTNJrTNd9sp7PX3lXSUu9AWlrZkyO-HhVbXFunVtfduDuTeVXxP8iw1wt6171CFbPmQJU_b3xCornzyFKmhSc36yvlDfoPPclWmWeyOfFEp9lVhQm0WhfDK7GiuRtaOxD-tOvpTjpcoZBeJb7bSg2OsneyeM_33a0WoPmjHw8WIxbroJz_PrfE72_TzbcTSDttKAv_e75PE48Vvx0661miFv4Gq8RBzMl2G3pQMEVCOm83v7BpodfN_YVJcqZJjVHMA70TZQ4K3L4_i9sIK9jJFfwEDVM7nsDnUu96n4vKs1fVvAuieCIPAJrfNOUMy7TwLvhnhUARsKnzmtNNrJuDhhBx-X93AHcG3micXgnqkFdKn6-ZUZ63I2KEdmjwKmLTRrv4n4eZKrRN-OrHPI4gLxJUhmyPAHzZrikMVBcDYfALqyki5SeKkwd4v0JAm87QzR4YwMdKErr0Xa5JrZqHGe2TZgVO4hIc-KrPw - body: - query: | - query { - protectedScalar - nested { - name - protected - } - protectedType { - name - nested - } - } - response: - body: - data: - protectedScalar: data from protected scalar - nested: - name: protected nested name - protected: protected nested - protectedType: - name: protected type name - nested: protected type nested diff --git a/tests/http/auth-jwt-const.yml b/tests/http/auth-jwt-const.yml deleted file mode 100644 index d50bd4d166..0000000000 --- a/tests/http/auth-jwt-const.yml +++ /dev/null @@ -1,67 +0,0 @@ -config: !file tests/http/config/auth-jwt-const.graphql -name: Auth with JWT loaded from const - -assert: - - request: - method: POST - url: http://localhost:8080/graphql - body: - query: | - query { - scalar - nested { - name - } - } - response: - body: - data: - scalar: data from public scalar - nested: - name: protected nested name - - - request: - method: POST - url: http://localhost:8080/graphql - body: - query: | - query { - protectedScalar - } - response: - body: - data: null - errors: - - message: Haven't found auth parameters - locations: - - column: 3 - line: 2 - - - request: - method: POST - url: http://localhost:8080/graphql - headers: - Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Ikk0OHFNSnA1NjZTU0tRb2dZWFl0SEJvOXE2WmNFS0hpeE5QZU5veFYxYzgifQ.eyJleHAiOjIwMTkwNTY0NDEuMCwiaXNzIjoibWUiLCJzdWIiOiJ5b3UiLCJhdWQiOlsidGhlbSJdfQ.cU-hJgVGWxK3-IBggYBChhf3FzibBKjuDLtq2urJ99FVXIGZls0VMXjyNW7yHhLLuif_9t2N5UIUIq-hwXVv7rrGRPCGrlqKU0jsUH251Spy7_ppG5_B2LsG3cBJcwkD4AVz8qjT3AaE_vYZ4WnH-CQ-F5Vm7wiYZgbdyU8xgKoH85KAxaCdJJlYOi8mApE9_zcdmTNJrTNd9sp7PX3lXSUu9AWlrZkyO-HhVbXFunVtfduDuTeVXxP8iw1wt6171CFbPmQJU_b3xCornzyFKmhSc36yvlDfoPPclWmWeyOfFEp9lVhQm0WhfDK7GiuRtaOxD-tOvpTjpcoZBeJb7bSg2OsneyeM_33a0WoPmjHw8WIxbroJz_PrfE72_TzbcTSDttKAv_e75PE48Vvx0661miFv4Gq8RBzMl2G3pQMEVCOm83v7BpodfN_YVJcqZJjVHMA70TZQ4K3L4_i9sIK9jJFfwEDVM7nsDnUu96n4vKs1fVvAuieCIPAJrfNOUMy7TwLvhnhUARsKnzmtNNrJuDhhBx-X93AHcG3micXgnqkFdKn6-ZUZ63I2KEdmjwKmLTRrv4n4eZKrRN-OrHPI4gLxJUhmyPAHzZrikMVBcDYfALqyki5SeKkwd4v0JAm87QzR4YwMdKErr0Xa5JrZqHGe2TZgVO4hIc-KrPw - body: - query: | - query { - protectedScalar - nested { - name - protected - } - protectedType { - name - nested - } - } - response: - body: - data: - protectedScalar: data from protected scalar - nested: - name: protected nested name - protected: protected nested - protectedType: - name: protected type name - nested: protected type nested diff --git a/tests/http/auth-jwt-remote.yml b/tests/http/auth-jwt-remote.yml deleted file mode 100644 index c915df6054..0000000000 --- a/tests/http/auth-jwt-remote.yml +++ /dev/null @@ -1,80 +0,0 @@ -config: !file tests/http/config/auth-jwt-remote.graphql -name: Auth with JWT loaded from remote - -mock: - - request: - url: http://localhost:3000/jwks - response: - body: - keys: - - kty: RSA - use: sig - alg: RS256 - kid: I48qMJp566SSKQogYXYtHBo9q6ZcEKHixNPeNoxV1c8 - n: ksMb5oMlhJ_HzAebCuBG6-v5Qc4J111ur7Aux6-8SbxzqFONsf2Bw6ATG8pAfNeZ-USA3_T1mGkYTDvfoggXnxsduWV_lePZKKOq_Qp_EDdzic1bVTJQDad3CXldR3wV6UFDtMx6cCLXxPZM5n76e7ybPt0iNgwoGpJE28emMZJXrnEUFzxwFMq61UlzWEumYqW3uOUVp7r5XAF5jQ_1nQAnpHBnRFzdNPVb3E6odMGu3jgp8mkPbPMP16Fund4LVplLz8yrsE9TdVrSdYJThylRWn_BwvJ0DjUcp8ibJya86iClUlixAmBwR9NdStHwQqHwmMXMKkTXo-ytRmSUobzxX9T8ESkij6iBhQpmDMD3FbkK30Y7pUVEBBOyDfNcWOhholjOj9CRrxu9to5rc2wvufe24VlbKb9wngS_uGfK4AYvVyrcjdYMFkdqw-Mft14HwzdO2BTS0TeMDZuLmYhj_bu5_g2Zu6PH5OpIXF6Fi8_679pCG8wWAcFQrFrM0eA70wD_SqD_BXn6pWRpFXlcRy_7PWTZ3QmC7ycQFR6Wc6Px44y1xDUoq3rH0RlZkeicfvP6FRlpjFU7xF6LjAfd9ciYBZfJll6PE7zf-i_ZXEslv-tJ5-30-I4Slwj0tDrZ2Z54OgAg07AIwAiI5o4y-0vmuhUscNpfZsGAGhE - e: AQAB - -assert: - - request: - method: POST - url: http://localhost:8080/graphql - body: - query: | - query { - scalar - nested { - name - } - } - response: - body: - data: - scalar: data from public scalar - nested: - name: protected nested name - - - request: - method: POST - url: http://localhost:8080/graphql - body: - query: | - query { - protectedScalar - } - response: - body: - data: null - errors: - - message: Haven't found auth parameters - locations: - - column: 3 - line: 2 - - - request: - method: POST - url: http://localhost:8080/graphql - headers: - Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Ikk0OHFNSnA1NjZTU0tRb2dZWFl0SEJvOXE2WmNFS0hpeE5QZU5veFYxYzgifQ.eyJleHAiOjIwMTkwNTY0NDEuMCwiaXNzIjoibWUiLCJzdWIiOiJ5b3UiLCJhdWQiOlsidGhlbSJdfQ.cU-hJgVGWxK3-IBggYBChhf3FzibBKjuDLtq2urJ99FVXIGZls0VMXjyNW7yHhLLuif_9t2N5UIUIq-hwXVv7rrGRPCGrlqKU0jsUH251Spy7_ppG5_B2LsG3cBJcwkD4AVz8qjT3AaE_vYZ4WnH-CQ-F5Vm7wiYZgbdyU8xgKoH85KAxaCdJJlYOi8mApE9_zcdmTNJrTNd9sp7PX3lXSUu9AWlrZkyO-HhVbXFunVtfduDuTeVXxP8iw1wt6171CFbPmQJU_b3xCornzyFKmhSc36yvlDfoPPclWmWeyOfFEp9lVhQm0WhfDK7GiuRtaOxD-tOvpTjpcoZBeJb7bSg2OsneyeM_33a0WoPmjHw8WIxbroJz_PrfE72_TzbcTSDttKAv_e75PE48Vvx0661miFv4Gq8RBzMl2G3pQMEVCOm83v7BpodfN_YVJcqZJjVHMA70TZQ4K3L4_i9sIK9jJFfwEDVM7nsDnUu96n4vKs1fVvAuieCIPAJrfNOUMy7TwLvhnhUARsKnzmtNNrJuDhhBx-X93AHcG3micXgnqkFdKn6-ZUZ63I2KEdmjwKmLTRrv4n4eZKrRN-OrHPI4gLxJUhmyPAHzZrikMVBcDYfALqyki5SeKkwd4v0JAm87QzR4YwMdKErr0Xa5JrZqHGe2TZgVO4hIc-KrPw - body: - query: | - query { - protectedScalar - nested { - name - protected - } - protectedType { - name - nested - } - } - response: - body: - data: - protectedScalar: data from protected scalar - nested: - name: protected nested name - protected: protected nested - protectedType: - name: protected type name - nested: protected type nested diff --git a/tests/http/auth.yml b/tests/http/auth.yml deleted file mode 100644 index d0d5b003a8..0000000000 --- a/tests/http/auth.yml +++ /dev/null @@ -1,135 +0,0 @@ -config: !file tests/http/config/auth.graphql -name: Auth with multiple auth providers - -env: - BASIC_AUTH: | - testuser1:$apr1$e3dp9qh2$fFIfHU9bilvVZBl8TxKzL/ - testuser2:$2y$10$wJ/mZDURcAOBIrswCAKFsO0Nk7BpHmWl/XuhF7lNm3gBAFH3ofsuu - testuser3:{SHA}Y2fEjdGT1W6nsLqtJbGUVeUp9e4= - - JWKS_AUTH: | - { - "keys": [ - { - "kty": "RSA", - "use": "sig", - "alg": "RS256", - "kid": "I48qMJp566SSKQogYXYtHBo9q6ZcEKHixNPeNoxV1c8", - "n": "ksMb5oMlhJ_HzAebCuBG6-v5Qc4J111ur7Aux6-8SbxzqFONsf2Bw6ATG8pAfNeZ-USA3_T1mGkYTDvfoggXnxsduWV_lePZKKOq_Qp_EDdzic1bVTJQDad3CXldR3wV6UFDtMx6cCLXxPZM5n76e7ybPt0iNgwoGpJE28emMZJXrnEUFzxwFMq61UlzWEumYqW3uOUVp7r5XAF5jQ_1nQAnpHBnRFzdNPVb3E6odMGu3jgp8mkPbPMP16Fund4LVplLz8yrsE9TdVrSdYJThylRWn_BwvJ0DjUcp8ibJya86iClUlixAmBwR9NdStHwQqHwmMXMKkTXo-ytRmSUobzxX9T8ESkij6iBhQpmDMD3FbkK30Y7pUVEBBOyDfNcWOhholjOj9CRrxu9to5rc2wvufe24VlbKb9wngS_uGfK4AYvVyrcjdYMFkdqw-Mft14HwzdO2BTS0TeMDZuLmYhj_bu5_g2Zu6PH5OpIXF6Fi8_679pCG8wWAcFQrFrM0eA70wD_SqD_BXn6pWRpFXlcRy_7PWTZ3QmC7ycQFR6Wc6Px44y1xDUoq3rH0RlZkeicfvP6FRlpjFU7xF6LjAfd9ciYBZfJll6PE7zf-i_ZXEslv-tJ5-30-I4Slwj0tDrZ2Z54OgAg07AIwAiI5o4y-0vmuhUscNpfZsGAGhE", - "e": "AQAB" - } - ] - } - -assert: - - request: - method: POST - url: http://localhost:8080/graphql - body: - query: | - query { - scalar - nested { - name - } - } - response: - body: - data: - scalar: data from public scalar - nested: - name: protected nested name - - - request: - method: POST - url: http://localhost:8080/graphql - body: - query: | - query { - protectedScalar - } - response: - body: - data: null - errors: - - message: Haven't found auth parameters - locations: - - column: 3 - line: 2 - - - request: - method: POST - url: http://localhost:8080/graphql - headers: - Authorization: Basic dGVzdHVzZXIxOnJhbmRvbV9wYXNzd29yZA== # wrong password - body: - query: | - query { - protectedScalar - } - response: - body: - data: null - errors: - - message: Auth validation failed - locations: - - column: 3 - line: 2 - - - request: - method: POST - url: http://localhost:8080/graphql - headers: - Authorization: Basic dGVzdHVzZXIyOm15cGFzc3dvcmQ= - body: - query: | - query { - protectedScalar - nested { - name - protected - } - protectedType { - name - nested - } - } - response: - body: - data: - protectedScalar: data from protected scalar - nested: - name: protected nested name - protected: protected nested - protectedType: - name: protected type name - nested: protected type nested - - - request: - method: POST - url: http://localhost:8080/graphql - headers: - Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Ikk0OHFNSnA1NjZTU0tRb2dZWFl0SEJvOXE2WmNFS0hpeE5QZU5veFYxYzgifQ.eyJleHAiOjIwMTkwNTY0NDEuMCwiaXNzIjoibWUiLCJzdWIiOiJ5b3UiLCJhdWQiOlsidGhlbSJdfQ.cU-hJgVGWxK3-IBggYBChhf3FzibBKjuDLtq2urJ99FVXIGZls0VMXjyNW7yHhLLuif_9t2N5UIUIq-hwXVv7rrGRPCGrlqKU0jsUH251Spy7_ppG5_B2LsG3cBJcwkD4AVz8qjT3AaE_vYZ4WnH-CQ-F5Vm7wiYZgbdyU8xgKoH85KAxaCdJJlYOi8mApE9_zcdmTNJrTNd9sp7PX3lXSUu9AWlrZkyO-HhVbXFunVtfduDuTeVXxP8iw1wt6171CFbPmQJU_b3xCornzyFKmhSc36yvlDfoPPclWmWeyOfFEp9lVhQm0WhfDK7GiuRtaOxD-tOvpTjpcoZBeJb7bSg2OsneyeM_33a0WoPmjHw8WIxbroJz_PrfE72_TzbcTSDttKAv_e75PE48Vvx0661miFv4Gq8RBzMl2G3pQMEVCOm83v7BpodfN_YVJcqZJjVHMA70TZQ4K3L4_i9sIK9jJFfwEDVM7nsDnUu96n4vKs1fVvAuieCIPAJrfNOUMy7TwLvhnhUARsKnzmtNNrJuDhhBx-X93AHcG3micXgnqkFdKn6-ZUZ63I2KEdmjwKmLTRrv4n4eZKrRN-OrHPI4gLxJUhmyPAHzZrikMVBcDYfALqyki5SeKkwd4v0JAm87QzR4YwMdKErr0Xa5JrZqHGe2TZgVO4hIc-KrPw - body: - query: | - query { - protectedScalar - nested { - name - protected - } - protectedType { - name - nested - } - } - response: - body: - data: - protectedScalar: data from protected scalar - nested: - name: protected nested name - protected: protected nested - protectedType: - name: protected type name - nested: protected type nested diff --git a/tests/http/config/auth-basic-const-env.graphql b/tests/http/config/auth-basic-const-env.graphql deleted file mode 100644 index eb9f5583b3..0000000000 --- a/tests/http/config/auth-basic-const-env.graphql +++ /dev/null @@ -1,20 +0,0 @@ -schema @server(port: 8000, graphiql: true, auth: [{id: "basic", basic: {htpasswd: "{{env.HTPASSWD_CONTENT}}"}}]) { - query: Query -} - -type Query { - scalar: String! @const(data: "data from public scalar") - protectedScalar: String! @protected @const(data: "data from protected scalar") - nested: Nested! - protectedType: ProtectedType -} - -type Nested { - name: String! @const(data: "protected nested name") - protected: String! @protected @const(data: "protected nested") -} - -type ProtectedType @protected { - name: String! @const(data: "protected type name") - nested: String! @const(data: "protected type nested") -} diff --git a/tests/http/config/auth-jwt-const-env.graphql b/tests/http/config/auth-jwt-const-env.graphql deleted file mode 100644 index 9b873ac214..0000000000 --- a/tests/http/config/auth-jwt-const-env.graphql +++ /dev/null @@ -1,20 +0,0 @@ -schema @server(port: 8000, graphiql: true, auth: [{jwt: {jwks: {data: "{{env.JWKS}}"}}, id: "jwt"}]) { - query: Query -} - -type Query { - scalar: String! @const(data: "data from public scalar") - protectedScalar: String! @protected @const(data: "data from protected scalar") - nested: Nested! - protectedType: ProtectedType -} - -type Nested { - name: String! @const(data: "protected nested name") - protected: String! @protected @const(data: "protected nested") -} - -type ProtectedType @protected { - name: String! @const(data: "protected type name") - nested: String! @const(data: "protected type nested") -} diff --git a/tests/http/config/auth-jwt-const.graphql b/tests/http/config/auth-jwt-const.graphql deleted file mode 100644 index 20f7289c38..0000000000 --- a/tests/http/config/auth-jwt-const.graphql +++ /dev/null @@ -1,47 +0,0 @@ -schema - @server( - port: 8000 - graphiql: true - auth: [ - { - jwt: { - jwks: { - data: """ - { - "keys": [ - { - "kty": "RSA", - "use": "sig", - "alg": "RS256", - "kid": "I48qMJp566SSKQogYXYtHBo9q6ZcEKHixNPeNoxV1c8", - "n": "ksMb5oMlhJ_HzAebCuBG6-v5Qc4J111ur7Aux6-8SbxzqFONsf2Bw6ATG8pAfNeZ-USA3_T1mGkYTDvfoggXnxsduWV_lePZKKOq_Qp_EDdzic1bVTJQDad3CXldR3wV6UFDtMx6cCLXxPZM5n76e7ybPt0iNgwoGpJE28emMZJXrnEUFzxwFMq61UlzWEumYqW3uOUVp7r5XAF5jQ_1nQAnpHBnRFzdNPVb3E6odMGu3jgp8mkPbPMP16Fund4LVplLz8yrsE9TdVrSdYJThylRWn_BwvJ0DjUcp8ibJya86iClUlixAmBwR9NdStHwQqHwmMXMKkTXo-ytRmSUobzxX9T8ESkij6iBhQpmDMD3FbkK30Y7pUVEBBOyDfNcWOhholjOj9CRrxu9to5rc2wvufe24VlbKb9wngS_uGfK4AYvVyrcjdYMFkdqw-Mft14HwzdO2BTS0TeMDZuLmYhj_bu5_g2Zu6PH5OpIXF6Fi8_679pCG8wWAcFQrFrM0eA70wD_SqD_BXn6pWRpFXlcRy_7PWTZ3QmC7ycQFR6Wc6Px44y1xDUoq3rH0RlZkeicfvP6FRlpjFU7xF6LjAfd9ciYBZfJll6PE7zf-i_ZXEslv-tJ5-30-I4Slwj0tDrZ2Z54OgAg07AIwAiI5o4y-0vmuhUscNpfZsGAGhE", - "e": "AQAB" - } - ] - } - """ - } - } - id: "jwt" - } - ] - ) { - query: Query -} - -type Query { - scalar: String! @const(data: "data from public scalar") - protectedScalar: String! @protected @const(data: "data from protected scalar") - nested: Nested! - protectedType: ProtectedType -} - -type Nested { - name: String! @const(data: "protected nested name") - protected: String! @protected @const(data: "protected nested") -} - -type ProtectedType @protected { - name: String! @const(data: "protected type name") - nested: String! @const(data: "protected type nested") -} diff --git a/tests/http/config/auth-jwt-remote.graphql b/tests/http/config/auth-jwt-remote.graphql deleted file mode 100644 index bcfe01893b..0000000000 --- a/tests/http/config/auth-jwt-remote.graphql +++ /dev/null @@ -1,21 +0,0 @@ -schema - @server(port: 8000, graphiql: true, auth: [{id: "jwt", jwt: {jwks: {remote: {url: "http://localhost:3000/jwks"}}}}]) { - query: Query -} - -type Query { - scalar: String! @const(data: "data from public scalar") - protectedScalar: String! @protected @const(data: "data from protected scalar") - nested: Nested! - protectedType: ProtectedType -} - -type Nested { - name: String! @const(data: "protected nested name") - protected: String! @protected @const(data: "protected nested") -} - -type ProtectedType @protected { - name: String! @const(data: "protected type name") - nested: String! @const(data: "protected type nested") -} diff --git a/tests/http/config/auth.graphql b/tests/http/config/auth.graphql deleted file mode 100644 index c6bf3fac36..0000000000 --- a/tests/http/config/auth.graphql +++ /dev/null @@ -1,28 +0,0 @@ -schema - @server( - port: 8000 - graphiql: true - auth: [ - {id: "basic", basic: {htpasswd: "{{env.BASIC_AUTH}}"}} - {id: "jwt", jwt: {jwks: {data: "{{env.JWKS_AUTH}}"}}} - ] - ) { - query: Query -} - -type Query { - scalar: String! @const(data: "data from public scalar") - protectedScalar: String! @protected @const(data: "data from protected scalar") - nested: Nested! - protectedType: ProtectedType -} - -type Nested { - name: String! @const(data: "protected nested name") - protected: String! @protected @const(data: "protected nested") -} - -type ProtectedType @protected { - name: String! @const(data: "protected type name") - nested: String! @const(data: "protected type nested") -} diff --git a/tests/http_spec.rs b/tests/http_spec.rs index 0d78302dde..9bd5081d80 100644 --- a/tests/http_spec.rs +++ b/tests/http_spec.rs @@ -5,7 +5,7 @@ use std::panic::AssertUnwindSafe; use std::path::PathBuf; use std::str::FromStr; use std::sync::{Arc, Once}; -use std::{env, fs, panic}; +use std::{fs, panic}; use anyhow::{anyhow, Context}; use derive_setters::Setters; @@ -196,26 +196,21 @@ impl HttpSpec { anyhow::Ok(spec) } - async fn server_context(&self) -> anyhow::Result>> { + async fn server_context(&self) -> Arc> { let http_client = init_http(&Upstream::default()); let config = match self.config.clone() { ConfigSource::File(file) => { let reader = ConfigReader::init(init_file(), http_client); - reader.read(&[file]).await? + reader.read(&[file]).await.unwrap() } ConfigSource::Inline(config) => config, }; - - for (k, v) in &self.env { - env::set_var(k, v.clone()); - } - - let blueprint = Blueprint::try_from(&config)?; + let blueprint = Blueprint::try_from(&config).unwrap(); let client = Arc::new(MockHttpClient { spec: self.clone() }); let http2_client = Arc::new(MockHttpClient { spec: self.clone() }); let env = Arc::new(Env::init(self.env.clone())); let server_context = AppContext::new(blueprint, client, http2_client, env.clone()); - Ok(Arc::new(server_context)) + Arc::new(server_context) } } @@ -408,7 +403,7 @@ async fn run(spec: HttpSpec, downstream_assertion: &&DownstreamAssertion) -> any let method = downstream_assertion.request.0.method.clone(); let headers = downstream_assertion.request.0.headers.clone(); let url = downstream_assertion.request.0.url.clone(); - let server_context = spec.server_context().await?; + let server_context = spec.server_context().await; let req = headers .into_iter() .fold(