From 0fcbc6bbe97e6dde941e9bc691ff9704416ea66b Mon Sep 17 00:00:00 2001 From: lonelyhentxi Date: Fri, 23 May 2025 02:54:53 +0800 Subject: [PATCH] feat: alter unsafe packages --- Cargo.lock | 411 ++++++++---------- Cargo.toml | 23 +- apps/recorder/Cargo.toml | 13 +- apps/recorder/src/app/config/mod.rs | 4 +- apps/recorder/src/auth/config.rs | 16 +- apps/recorder/src/auth/errors.rs | 8 +- apps/recorder/src/auth/oidc.rs | 117 ++--- apps/recorder/src/auth/service.rs | 68 ++- apps/recorder/src/errors/app_error.rs | 2 +- .../recorder/src/graphql/infra/filter/json.rs | 4 +- .../src/graphql/views/subscription.rs | 2 +- apps/webui/src/infra/graphql/gql/gql.ts | 6 +- apps/webui/src/infra/graphql/gql/graphql.ts | 188 +++++++- packages/downloader/Cargo.toml | 7 +- packages/util-derive/src/lib.rs | 6 + 15 files changed, 470 insertions(+), 405 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a31832a..345c988 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -178,12 +178,12 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa" dependencies = [ "anstyle", - "once_cell", + "once_cell_polyfill", "windows-sys 0.59.0", ] @@ -195,9 +195,9 @@ checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "apalis" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf157b59923258974a886572a18fe47b401daeca43b44c719b73736d8788840" +checksum = "23f330bf01eb81cc310733c141749e3c3da04db9cb59425ee8537073b3a4bd48" dependencies = [ "apalis-core", "futures", @@ -211,9 +211,9 @@ dependencies = [ [[package]] name = "apalis-core" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbbc8dc67f007145277cb5977c730c4fa7fb07244e83d69d1c5a43cb4d124fa" +checksum = "83dc559004ae0a16a7467f10adae65703f865785282e80ca1ce88905571f5ebd" dependencies = [ "futures", "futures-timer", @@ -227,9 +227,9 @@ dependencies = [ [[package]] name = "apalis-sql" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34757d9408f39656451c524ca10fe6331d59aaf25cda60bd70d677a4213efead" +checksum = "d28022bb338bf145accd44520bb8f2fe16c6a6a158598ef2ccf9e3db45101f85" dependencies = [ "apalis-core", "async-stream", @@ -325,9 +325,9 @@ dependencies = [ [[package]] name = "async-graphql" -version = "7.0.16" +version = "7.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3ee559e72d983e7e04001ba3bf32e6b71c1d670595780723727fd8a29d36e87" +checksum = "036618f842229ba0b89652ffe425f96c7c16a49f7e3cb23b56fca7f61fd74980" dependencies = [ "async-graphql-derive", "async-graphql-parser", @@ -364,9 +364,9 @@ dependencies = [ [[package]] name = "async-graphql-axum" -version = "7.0.16" +version = "7.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95b41ba3c0f4ecccd73bf7e7aa7be3c41ff054968e988317bd9133ed210a4a2" +checksum = "8725874ecfbf399e071150b8619c4071d7b2b7a2f117e173dddef53c6bdb6bb1" dependencies = [ "async-graphql", "axum", @@ -381,9 +381,9 @@ dependencies = [ [[package]] name = "async-graphql-derive" -version = "7.0.16" +version = "7.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29db05b624fb6352fc11bfe30c54ab1b16a1fe937d7c05a783f4e88ef1292b3b" +checksum = "fd45deb3dbe5da5cdb8d6a670a7736d735ba65b455328440f236dfb113727a3d" dependencies = [ "Inflector", "async-graphql-parser", @@ -398,9 +398,9 @@ dependencies = [ [[package]] name = "async-graphql-parser" -version = "7.0.16" +version = "7.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4904895044116aab098ca82c6cec831ec43ed99efd04db9b70a390419bc88c5b" +checksum = "60b7607e59424a35dadbc085b0d513aa54ec28160ee640cf79ec3b634eba66d3" dependencies = [ "async-graphql-value", "pest", @@ -410,9 +410,9 @@ dependencies = [ [[package]] name = "async-graphql-value" -version = "7.0.16" +version = "7.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0cde74de18e3a00c5dd5cfa002ab6f532e1a06c2a79ee6671e2fc353b400b92" +checksum = "34ecdaff7c9cffa3614a9f9999bf9ee4c3078fe3ce4d6a6e161736b56febf2de" dependencies = [ "bytes", "indexmap 2.9.0", @@ -934,9 +934,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.23" +version = "1.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766" +checksum = "16595d3be041c03b09d08d0858631facccee9221e579704070e6e9e4915d3bc7" dependencies = [ "jobserver", "libc", @@ -1039,9 +1039,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.38" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed93b9805f8ba930df42c2590f05453d5ec36cbb85d018868a5b24d31f6ac000" +checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" dependencies = [ "clap_builder", "clap_derive", @@ -1049,9 +1049,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.38" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "379026ff283facf611b0ea629334361c4211d1b12ee01024eec1591133b04120" +checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" dependencies = [ "anstream", "anstyle", @@ -1216,7 +1216,7 @@ checksum = "2eac901828f88a5241ee0600950ab981148a18f2f756900ffba1b125ca6a3ef9" dependencies = [ "cookie", "document-features", - "idna 1.0.3", + "idna", "log", "publicsuffix", "serde", @@ -1238,9 +1238,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" dependencies = [ "core-foundation-sys", "libc", @@ -1698,12 +1698,6 @@ dependencies = [ "litrs", ] -[[package]] -name = "dotenv" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" - [[package]] name = "dotenvy" version = "0.15.7" @@ -2006,7 +2000,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", - "toml", + "toml 0.8.22", "uncased", "version_check", ] @@ -2476,30 +2470,6 @@ dependencies = [ "hashbrown 0.15.3", ] -[[package]] -name = "headers" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" -dependencies = [ - "base64 0.21.7", - "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" -dependencies = [ - "http", -] - [[package]] name = "heck" version = "0.4.1" @@ -2618,9 +2588,9 @@ dependencies = [ [[package]] name = "http-cache" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b65cd1687caf2c7fff496741a2f264c26f54e6d6cec03dac8f276fa4e5430e" +checksum = "7e883defacf53960c7717d9e928dc8667be9501d9f54e6a8b7703d7a30320e9c" dependencies = [ "async-trait", "bincode", @@ -2635,9 +2605,9 @@ dependencies = [ [[package]] name = "http-cache-reqwest" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "735586904a5ce0c13877c57cb4eb8195eb7c11ec1ffd64d4db053fb8559ca62e" +checksum = "e076afd9d376f09073b515ce95071b29393687d98ed521948edb899195595ddf" dependencies = [ "anyhow", "async-trait", @@ -2737,11 +2707,10 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.5" +version = "0.27.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" +checksum = "03a01595e11bdcec50946522c32dde3fc6914743000a68b93000965f2f02406d" dependencies = [ - "futures-util", "http", "hyper", "hyper-util", @@ -2750,7 +2719,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", - "webpki-roots 0.26.11", + "webpki-roots", ] [[package]] @@ -2771,22 +2740,28 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" +checksum = "b1c293b6b3d21eca78250dc7dbebd6b9210ec5530e038cbfe0661b5c47ab06e8" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", + "futures-core", "futures-util", "http", "http-body", "hyper", + "ipnet", "libc", + "percent-encoding", "pin-project-lite", "socket2", + "system-configuration", "tokio", "tower-service", "tracing", + "windows-registry", ] [[package]] @@ -2877,9 +2852,9 @@ checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2549ca8c7241c82f59c80ba2a6f415d931c5b58d24fb8412caa1a1f02c49139a" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", @@ -2893,9 +2868,9 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8197e866e47b68f8f7d95249e172903bec06004b18b2937f1095d40a0c57de04" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" @@ -2920,16 +2895,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "idna" version = "1.0.3" @@ -3048,6 +3013,7 @@ dependencies = [ "regex", "serde", "similar", + "toml 0.5.11", ] [[package]] @@ -3062,6 +3028,15 @@ dependencies = [ "web-sys", ] +[[package]] +name = "intervaltree" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "270bc34e57047cab801a8c871c124d9dc7132f6473c6401f645524f4e6edd111" +dependencies = [ + "smallvec", +] + [[package]] name = "ipnet" version = "2.11.0" @@ -3074,6 +3049,16 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf370abdafd54d13e54a620e8c3e1145f28e46cc9d704bc6d94414559df41763" +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -3140,43 +3125,21 @@ dependencies = [ ] [[package]] -name = "jsonwebtoken" -version = "9.3.1" +name = "jwtk" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" +checksum = "14924a83612db7dfb6722e81a30bfe11e25ef89b1df0dc81128974371e3e64d8" dependencies = [ "base64 0.22.1", - "js-sys", - "pem", - "ring", - "serde", - "serde_json", - "simple_asn1", -] - -[[package]] -name = "jwt-authorizer" -version = "0.15.0" -source = "git+https://github.com/blablacio/jwt-authorizer.git?rev=e956774#e95677413b622ab107d941855615267868b82c41" -dependencies = [ - "axum", - "chrono", - "futures-core", - "futures-util", - "headers", - "http", - "http-body-util", - "jsonwebtoken", - "pin-project", + "foreign-types", + "openssl", + "openssl-sys", "reqwest", "serde", "serde_json", - "thiserror 2.0.12", + "serde_with", + "smallvec", "tokio", - "tower-http", - "tower-layer", - "tower-service", - "tracing", ] [[package]] @@ -3373,12 +3336,12 @@ dependencies = [ [[package]] name = "librqbit" version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b2acdb059277c92c39628b9b78b7cb4fe1148877150d2d63e21c52b35b1d08" +source = "git+https://github.com/ikatson/rqbit.git?rev=0936730#093673064a49af688b04cf623e435ef40894ca3d" dependencies = [ "anyhow", "arc-swap", "async-backtrace", + "async-compression", "async-stream", "async-trait", "backoff", @@ -3392,6 +3355,7 @@ dependencies = [ "governor", "hex 0.4.3", "http", + "intervaltree", "itertools 0.14.0", "librqbit-bencode", "librqbit-buffers", @@ -3429,8 +3393,7 @@ dependencies = [ [[package]] name = "librqbit-bencode" version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b202e1bf6fb0e2ccbed2ec253135f40f8f73bb14f9bc5d7666389701b20ae30" +source = "git+https://github.com/ikatson/rqbit.git?rev=0936730#093673064a49af688b04cf623e435ef40894ca3d" dependencies = [ "anyhow", "bytes", @@ -3443,8 +3406,7 @@ dependencies = [ [[package]] name = "librqbit-buffers" version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78c78b907d6171a7191c162b2b60db46d254ebde6a95282b77372af556c1463" +source = "git+https://github.com/ikatson/rqbit.git?rev=0936730#093673064a49af688b04cf623e435ef40894ca3d" dependencies = [ "bytes", "librqbit-clone-to-owned", @@ -3454,8 +3416,7 @@ dependencies = [ [[package]] name = "librqbit-clone-to-owned" version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dabe584079813bc1bb675eb8cddfcf378e97590e5927af594e7596b0946757d" +source = "git+https://github.com/ikatson/rqbit.git?rev=0936730#093673064a49af688b04cf623e435ef40894ca3d" dependencies = [ "bytes", ] @@ -3463,8 +3424,7 @@ dependencies = [ [[package]] name = "librqbit-core" version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ff142fc73650330e89173e5da3621240d02200d4198823c9c4c5c3a9efc61ae" +source = "git+https://github.com/ikatson/rqbit.git?rev=0936730#093673064a49af688b04cf623e435ef40894ca3d" dependencies = [ "anyhow", "assert_cfg", @@ -3488,8 +3448,7 @@ dependencies = [ [[package]] name = "librqbit-dht" version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c569560143642804e4a10c08b9b12c6f786891a0747dc98b9477b03ae123182b" +source = "git+https://github.com/ikatson/rqbit.git?rev=0936730#093673064a49af688b04cf623e435ef40894ca3d" dependencies = [ "anyhow", "backoff", @@ -3517,8 +3476,7 @@ dependencies = [ [[package]] name = "librqbit-peer-protocol" version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ee2a13d91f4764ca99c92d7cff9e194cb0f5b6b3277c5b318e3c849872ba0d" +source = "git+https://github.com/ikatson/rqbit.git?rev=0936730#093673064a49af688b04cf623e435ef40894ca3d" dependencies = [ "anyhow", "bincode", @@ -3536,8 +3494,7 @@ dependencies = [ [[package]] name = "librqbit-sha1-wrapper" version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79373a02db73159e4de7ca5d27b6eeae2d540df66c6801db2b01c5513d087524" +source = "git+https://github.com/ikatson/rqbit.git?rev=0936730#093673064a49af688b04cf623e435ef40894ca3d" dependencies = [ "assert_cfg", "crypto-hash", @@ -3546,8 +3503,7 @@ dependencies = [ [[package]] name = "librqbit-tracker-comms" version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f319b9abe4850284e7559d02da51ebba411191c474c9e0842d2adeecda072f4" +source = "git+https://github.com/ikatson/rqbit.git?rev=0936730#093673064a49af688b04cf623e435ef40894ca3d" dependencies = [ "anyhow", "async-stream", @@ -3556,10 +3512,12 @@ dependencies = [ "librqbit-bencode", "librqbit-buffers", "librqbit-core", + "parking_lot 0.12.3", "rand 0.8.5", "reqwest", "serde", "tokio", + "tokio-util", "tracing", "url", "urlencoding", @@ -3568,8 +3526,7 @@ dependencies = [ [[package]] name = "librqbit-upnp" version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545aad6124c97201055983137e12a19f34acad565120c3cd30596cbd72e8fa86" +source = "git+https://github.com/ikatson/rqbit.git?rev=0936730#093673064a49af688b04cf623e435ef40894ca3d" dependencies = [ "anyhow", "bstr", @@ -3861,14 +3818,14 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4187,6 +4144,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + [[package]] name = "opaque-debug" version = "0.3.1" @@ -4195,9 +4158,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "opendal" -version = "0.53.2" +version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ff9e9656d1cb3c58582ea18e6d9e71076a7ab2614207821d1242d7da2daed5" +checksum = "f947c4efbca344c1a125753366033c8107f552b2e3f8251815ed1908f116ca3e" dependencies = [ "anyhow", "async-trait", @@ -4253,9 +4216,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.72" +version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ "bitflags 2.9.1", "cfg-if", @@ -4285,9 +4248,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.108" +version = "0.9.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", @@ -4543,16 +4506,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "pem" -version = "3.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" -dependencies = [ - "base64 0.22.1", - "serde", -] - [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -4615,9 +4568,9 @@ dependencies = [ [[package]] name = "pgvector" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0e8871b6d7ca78348c6cd29b911b94851f3429f0cd403130ca17f26c1fb91a6" +checksum = "fc58e2d255979a31caa7cabfa7aac654af0354220719ab7a68520ae7a91e8c0b" dependencies = [ "serde", ] @@ -4886,7 +4839,7 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42ea446cab60335f76979ec15e12619a2165b5ae2c12166bef27d283a9fadf" dependencies = [ - "idna 1.0.3", + "idna", "psl-types", ] @@ -5131,7 +5084,7 @@ dependencies = [ "clap", "cocoon", "ctor", - "dotenv", + "dotenvy", "downloader", "fancy-regex", "fetch", @@ -5142,7 +5095,7 @@ dependencies = [ "insta", "ipnetwork", "itertools 0.14.0", - "jwt-authorizer", + "jwtk", "lazy_static", "lightningcss", "log", @@ -5168,7 +5121,6 @@ dependencies = [ "serde_json", "serde_variant", "serde_with", - "serde_yaml", "serial_test", "snafu", "tera", @@ -5300,9 +5252,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.15" +version = "0.12.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +checksum = "e98ff6b0dbbe4d5a37318f433d4fc82babd21631f194d370409ceb2e40b2f0b5" dependencies = [ "base64 0.22.1", "bytes", @@ -5330,27 +5282,25 @@ dependencies = [ "pin-project-lite", "quinn", "rustls", - "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", - "system-configuration", "tokio", "tokio-native-tls", "tokio-rustls", "tokio-socks", "tokio-util", "tower", + "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 0.26.11", - "windows-registry", + "webpki-roots", ] [[package]] @@ -5667,9 +5617,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" @@ -5752,9 +5702,9 @@ dependencies = [ [[package]] name = "sea-orm" -version = "1.1.11" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7cf58b28bcf1e053539c38afbb60d963ac8e1db87f6109db7b0eff4cbeaefb3" +checksum = "18b7272b88bd608cd846de24f41b74a0315a135fe761b0aed4ec1ce6a6327a93" dependencies = [ "async-stream", "async-trait", @@ -5781,9 +5731,9 @@ dependencies = [ [[package]] name = "sea-orm-cli" -version = "1.1.11" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0885ce200adaa527c696f6114f1a014c74801fa9c62a2b1bccfdec9af381108c" +checksum = "4a4961b0d9098a9dc992d6e75fb761f9e5c442bb46746eeffa08e47b53759fce" dependencies = [ "chrono", "clap", @@ -5791,6 +5741,7 @@ dependencies = [ "glob", "regex", "sea-schema", + "sqlx", "tracing", "tracing-subscriber", "url", @@ -5798,9 +5749,9 @@ dependencies = [ [[package]] name = "sea-orm-macros" -version = "1.1.11" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac37512fde1f5b9ef71ec773cfabb90ad3b68c27e53131ff38763c247fcbb2d" +checksum = "2c38255a6b2e6d1ae2d5df35696507a345f03c036ae32caeb0a3b922dbab610d" dependencies = [ "heck 0.5.0", "proc-macro-crate", @@ -5813,9 +5764,9 @@ dependencies = [ [[package]] name = "sea-orm-migration" -version = "1.1.11" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13f81e0ae079274b7eaa7b0234ae57b4a4f51619f53f3996d47580b378e0b26b" +checksum = "82f58c3b1dcf6c137f08394f0228f9baf1574a2a799e93dc5da3cd9228bef9c5" dependencies = [ "async-trait", "clap", @@ -5829,9 +5780,9 @@ dependencies = [ [[package]] name = "sea-query" -version = "0.32.5" +version = "0.32.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5506de3a33d9ee4ee161c5847acb87fe4f82ced6649afc9eabeb8df6f40ba94a" +checksum = "64c91783d1514b99754fc6a4079081dcc2c587dadbff65c48c7f62297443536a" dependencies = [ "bigdecimal", "chrono", @@ -5882,7 +5833,9 @@ checksum = "2239ff574c04858ca77485f112afea1a15e53135d3097d0c86509cef1def1338" dependencies = [ "futures", "sea-query", + "sea-query-binder", "sea-schema-derive", + "sqlx", ] [[package]] @@ -5952,7 +5905,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" dependencies = [ "bitflags 2.9.1", - "core-foundation 0.10.0", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -6279,18 +6232,6 @@ version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" -[[package]] -name = "simple_asn1" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" -dependencies = [ - "num-bigint", - "num-traits", - "thiserror 2.0.12", - "time", -] - [[package]] name = "siphasher" version = "1.0.1" @@ -6337,9 +6278,9 @@ dependencies = [ [[package]] name = "snafu" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "223891c85e2a29c3fe8fb900c1fae5e69c2e42415e3177752e8718475efa5019" +checksum = "320b01e011bf8d5d7a4a4a4be966d9160968935849c83b918827f6a435e7f627" dependencies = [ "futures-core", "pin-project", @@ -6348,9 +6289,9 @@ dependencies = [ [[package]] name = "snafu-derive" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c3c6b7927ffe7ecaa769ee0e3994da3b8cafc8f444578982c83ecb161af917" +checksum = "1961e2ef424c1424204d3a5d6975f934f56b6d50ff5732382d84ebf460e147f7" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -6360,9 +6301,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -6398,9 +6339,9 @@ dependencies = [ [[package]] name = "sqlx" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c3a85280daca669cfd3bcb68a337882a8bc57ec882f72c5d13a430613a738e" +checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" dependencies = [ "sqlx-core", "sqlx-macros", @@ -6411,9 +6352,9 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f743f2a3cea30a58cd479013f75550e879009e3a02f616f18ca699335aa248c3" +checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" dependencies = [ "base64 0.22.1", "bigdecimal", @@ -6435,7 +6376,6 @@ dependencies = [ "once_cell", "percent-encoding", "rust_decimal", - "rustls", "serde", "serde_json", "sha2 0.10.9", @@ -6447,14 +6387,13 @@ dependencies = [ "tracing", "url", "uuid", - "webpki-roots 0.26.11", ] [[package]] name = "sqlx-macros" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4200e0fde19834956d4252347c12a083bdcb237d7a1a1446bffd8768417dce" +checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" dependencies = [ "proc-macro2", "quote", @@ -6465,9 +6404,9 @@ dependencies = [ [[package]] name = "sqlx-macros-core" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882ceaa29cade31beca7129b6beeb05737f44f82dbe2a9806ecea5a7093d00b7" +checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" dependencies = [ "dotenvy", "either", @@ -6484,16 +6423,15 @@ dependencies = [ "sqlx-postgres", "sqlx-sqlite", "syn 2.0.101", - "tempfile", "tokio", "url", ] [[package]] name = "sqlx-mysql" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0afdd3aa7a629683c2d750c2df343025545087081ab5942593a5288855b1b7a7" +checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" dependencies = [ "atoi", "base64 0.22.1", @@ -6538,9 +6476,9 @@ dependencies = [ [[package]] name = "sqlx-postgres" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0bedbe1bbb5e2615ef347a5e9d8cd7680fb63e77d9dafc0f29be15e53f1ebe6" +checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" dependencies = [ "atoi", "base64 0.22.1", @@ -6581,9 +6519,9 @@ dependencies = [ [[package]] name = "sqlx-sqlite" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c26083e9a520e8eb87a06b12347679b142dc2ea29e6e409f805644a7a979a5bc" +checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" dependencies = [ "atoi", "chrono", @@ -7025,9 +6963,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.45.0" +version = "1.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", "bytes", @@ -7137,6 +7075,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "toml" version = "0.8.22" @@ -7202,7 +7149,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fdb0c213ca27a9f57ab69ddb290fd80d970922355b83ae380b395d3986b8a2e" dependencies = [ "async-compression", - "base64 0.22.1", "bitflags 2.9.1", "bytes", "futures-core", @@ -7212,12 +7158,14 @@ dependencies = [ "http-body-util", "http-range-header", "httpdate", + "iri-string", "mime", "mime_guess", "percent-encoding", "pin-project-lite", "tokio", "tokio-util", + "tower", "tower-layer", "tower-service", "tracing", @@ -7544,12 +7492,12 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna", "percent-encoding", "serde", ] @@ -7609,9 +7557,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ "getrandom 0.3.3", "js-sys", @@ -7802,15 +7750,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki-roots" -version = "0.26.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" -dependencies = [ - "webpki-roots 1.0.0", -] - [[package]] name = "webpki-roots" version = "1.0.0" @@ -7894,15 +7833,15 @@ dependencies = [ [[package]] name = "windows-core" -version = "0.61.1" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46ec44dc15085cea82cf9c78f85a9114c463a369786585ad2882d1ff0b0acf40" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", "windows-link", "windows-result", - "windows-strings 0.4.1", + "windows-strings 0.4.2", ] [[package]] @@ -7967,9 +7906,9 @@ dependencies = [ [[package]] name = "windows-result" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b895b5356fc36103d0f64dd1e94dfa7ac5633f1c9dd6e80fe9ec4adef69e09d" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ "windows-link", ] @@ -7985,9 +7924,9 @@ dependencies = [ [[package]] name = "windows-strings" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a7ab927b2637c19b3dbe0965e75d8f2d30bdd697a1516191cad2ec4df8fb28a" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ "windows-link", ] diff --git a/Cargo.toml b/Cargo.toml index 108cdd9..e610266 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,13 @@ util-derive = { path = "./packages/util-derive" } fetch = { path = "./packages/fetch" } downloader = { path = "./packages/downloader" } +reqwest = { version = "0.12", features = [ + "charset", + "http2", + "json", + "macos-system-configuration", + "cookies", +] } moka = "0.12" futures = "0.3" quirks_path = "0.1" @@ -24,7 +31,12 @@ testcontainers = { version = "0.24" } testcontainers-modules = { version = "0.12" } testcontainers-ext = { version = "0.1.0", features = ["tracing"] } serde = { version = "1", features = ["derive"] } -tokio = { version = "1", features = ["macros", "fs", "rt-multi-thread"] } +tokio = { version = "1.45.1", features = [ + "macros", + "fs", + "rt-multi-thread", + "signal", +] } serde_json = "1" async-trait = "0.1" tracing = "0.1" @@ -37,19 +49,10 @@ serde_with = "3" regex = "1.11" lazy_static = "1.5" axum = { version = "0.8.3", features = ["macros"] } -reqwest = { version = "0.12", default-features = false, features = [ - "charset", - "http2", - "json", - "macos-system-configuration", - "rustls-tls", - "cookies", -] } tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] } axum-extra = "0.10" mockito = { version = "1.6.1" } convert_case = "0.8" [patch.crates-io] -jwt-authorizer = { git = "https://github.com/blablacio/jwt-authorizer.git", rev = "e956774" } seaography = { git = "https://github.com/dumtruck/seaography.git", rev = "10ba248" } diff --git a/apps/recorder/Cargo.toml b/apps/recorder/Cargo.toml index 214c2a5..48c7277 100644 --- a/apps/recorder/Cargo.toml +++ b/apps/recorder/Cargo.toml @@ -59,13 +59,13 @@ mockito = { workspace = true, optional = true } sea-orm = { version = "1.1", features = [ "sqlx-sqlite", "sqlx-postgres", - "runtime-tokio-rustls", + "runtime-tokio", "macros", "debug-print", ] } figment = { version = "0.10", features = ["toml", "json", "env", "yaml"] } uuid = { version = "1.6.0", features = ["v4"] } -sea-orm-migration = { version = "1.1", features = ["runtime-tokio-rustls"] } +sea-orm-migration = { version = "1.1", features = ["runtime-tokio"] } rss = "2" fancy-regex = "0.14" maplit = "1.0.2" @@ -76,7 +76,6 @@ zune-image = "0.4.15" once_cell = "1.20.2" scraper = "0.23" -jwt-authorizer = "0.15.0" log = "0.4" async-graphql = { version = "7", features = ["dynamic-schema"] } async-graphql-axum = "7" @@ -102,8 +101,8 @@ tower-http = { version = "0.6", features = [ "compression-full", ] } tera = "1.20.0" -openidconnect = { version = "4", features = ["rustls-tls"] } -dotenv = "0.15.0" +openidconnect = { version = "4" } +dotenvy = "0.15.7" http = "1.2.0" async-stream = "0.3.6" serde_variant = "0.1.3" @@ -111,7 +110,6 @@ tracing-appender = "0.2.3" clap = "4.5.31" ipnetwork = "0.21.1" typed-builder = "0.21.0" -serde_yaml = "0.9.34" apalis = { version = "0.7", features = ["limit", "tracing", "catch-panic"] } apalis-sql = { version = "0.7", features = ["postgres"] } cocoon = { version = "0.4.3", features = ["getrandom", "thiserror"] } @@ -119,11 +117,12 @@ rand = "0.9.1" rust_decimal = "1.37.1" reqwest_cookie_store = "0.8.0" nanoid = "0.4.0" +jwtk = "0.4.0" [dev-dependencies] serial_test = "3" -insta = { version = "1", features = ["redactions", "yaml", "filters"] } +insta = { version = "1", features = ["redactions", "toml", "filters"] } rstest = "0.25" ctor = "0.4.0" mockito = { workspace = true } diff --git a/apps/recorder/src/app/config/mod.rs b/apps/recorder/src/app/config/mod.rs index 3dac85a..56d8802 100644 --- a/apps/recorder/src/app/config/mod.rs +++ b/apps/recorder/src/app/config/mod.rs @@ -110,12 +110,12 @@ impl AppConfig { for f in try_filenames.iter() { let p = try_dotenv_file_or_dir_path.join(f); if p.exists() && p.is_file() { - dotenv::from_path(p)?; + dotenvy::from_path(p)?; break; } } } else if try_dotenv_file_or_dir_path.is_file() { - dotenv::from_path(try_dotenv_file_or_dir_path)?; + dotenvy::from_path(try_dotenv_file_or_dir_path)?; break; } } diff --git a/apps/recorder/src/auth/config.rs b/apps/recorder/src/auth/config.rs index d47fc6f..3b5396a 100644 --- a/apps/recorder/src/auth/config.rs +++ b/apps/recorder/src/auth/config.rs @@ -1,6 +1,8 @@ -use jwt_authorizer::OneOrArray; +use std::collections::HashMap; + +use jwtk::OneOrMany; use serde::{Deserialize, Serialize}; -use serde_with::{NoneAsEmptyString, serde_as}; +use serde_with::serde_as; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct BasicAuthConfig { @@ -22,13 +24,9 @@ pub struct OidcAuthConfig { #[serde(rename = "oidc_client_secret")] pub client_secret: String, #[serde(rename = "oidc_extra_scopes")] - pub extra_scopes: Option>, - #[serde_as(as = "NoneAsEmptyString")] - #[serde(rename = "oidc_extra_claim_key")] - pub extra_claim_key: Option, - #[serde(rename = "oidc_extra_claim_value")] - #[serde_as(as = "NoneAsEmptyString")] - pub extra_claim_value: Option, + pub extra_scopes: Option>, + #[serde(rename = "oidc_extra_claims")] + pub extra_claims: Option>>, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] diff --git a/apps/recorder/src/auth/errors.rs b/apps/recorder/src/auth/errors.rs index e661231..04c9abd 100644 --- a/apps/recorder/src/auth/errors.rs +++ b/apps/recorder/src/auth/errors.rs @@ -27,10 +27,6 @@ pub enum AuthError { FindAuthRecordError, #[snafu(display("Invalid credentials"))] BasicInvalidCredentials, - #[snafu(transparent)] - OidcInitError { - source: jwt_authorizer::error::InitError, - }, #[snafu(display("Invalid oidc provider meta client error: {source}"))] OidcProviderHttpClientError { source: HttpClientError }, #[snafu(transparent)] @@ -66,8 +62,10 @@ pub enum AuthError { OidcSignatureVerificationError { source: SignatureVerificationError }, #[snafu(transparent)] OidcSigningError { source: SigningError }, + #[snafu(display("Missing Bearer token"))] + OidcMissingBearerToken, #[snafu(transparent)] - OidcJwtAuthError { source: jwt_authorizer::AuthError }, + OidcJwtkError { source: jwtk::Error }, #[snafu(display("Extra scopes {expected} do not match found scopes {found}"))] OidcExtraScopesMatchError { expected: String, found: String }, #[snafu(display("Extra claim {key} does not match expected value {expected}, found {found}"))] diff --git a/apps/recorder/src/auth/oidc.rs b/apps/recorder/src/auth/oidc.rs index cdb933a..a1e27b9 100644 --- a/apps/recorder/src/auth/oidc.rs +++ b/apps/recorder/src/auth/oidc.rs @@ -12,8 +12,9 @@ use axum::{ http::{HeaderValue, request::Parts}, }; use fetch::{HttpClient, client::HttpClientError}; +use http::header::AUTHORIZATION; use itertools::Itertools; -use jwt_authorizer::{NumericDate, OneOrArray, authorizer::Authorizer}; +use jwtk::jwk::RemoteJwksVerifier; use moka::future::Cache; use openidconnect::{ AccessTokenHash, AuthorizationCode, ClientId, ClientSecret, CsrfToken, IssuerUrl, Nonce, @@ -77,21 +78,6 @@ impl<'c> openidconnect::AsyncHttpClient<'c> for OidcHttpClient { #[derive(Deserialize, Serialize, Clone, Debug)] pub struct OidcAuthClaims { - #[serde(skip_serializing_if = "Option::is_none")] - pub iss: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub sub: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub aud: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub exp: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub nbf: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub iat: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub jti: Option, - #[serde(skip_serializing_if = "Option::is_none")] pub scope: Option, #[serde(flatten)] pub custom: HashMap, @@ -101,40 +87,6 @@ impl OidcAuthClaims { pub fn scopes(&self) -> std::str::Split<'_, char> { self.scope.as_deref().unwrap_or_default().split(',') } - - pub fn get_claim(&self, key: &str) -> Option { - match key { - "iss" => self.iss.clone(), - "sub" => self.sub.clone(), - "aud" => self.aud.as_ref().map(|s| s.iter().join(",")), - "exp" => self.exp.clone().map(|s| s.0.to_string()), - "nbf" => self.nbf.clone().map(|s| s.0.to_string()), - "iat" => self.iat.clone().map(|s| s.0.to_string()), - "jti" => self.jti.clone(), - "scope" => self.scope.clone(), - key => self.custom.get(key).map(|s| s.to_string()), - } - } - - pub fn has_claim(&self, key: &str) -> bool { - match key { - "iss" => self.iss.is_some(), - "sub" => self.sub.is_some(), - "aud" => self.aud.is_some(), - "exp" => self.exp.is_some(), - "nbf" => self.nbf.is_some(), - "iat" => self.iat.is_some(), - "jti" => self.jti.is_some(), - "scope" => self.scope.is_some(), - key => self.custom.contains_key(key), - } - } - - pub fn contains_audience(&self, aud: &str) -> bool { - self.aud - .as_ref() - .is_some_and(|arr| arr.iter().any(|s| s == aud)) - } } #[derive(Debug, Clone, Serialize)] @@ -164,7 +116,7 @@ pub struct OidcAuthCallbackPayload { pub struct OidcAuthService { pub config: OidcAuthConfig, - pub api_authorizer: Authorizer, + pub jwk_verifier: RemoteJwksVerifier, pub oidc_provider_client: Arc, pub oidc_request_cache: Cache, } @@ -317,47 +269,68 @@ impl AuthServiceTrait for OidcAuthService { request: &mut Parts, ) -> Result { let config = &self.config; - let token = self - .api_authorizer - .extract_token(&request.headers) - .ok_or(jwt_authorizer::AuthError::MissingToken())?; + let token = request + .headers + .get(AUTHORIZATION) + .and_then(|authorization| { + authorization + .to_str() + .ok() + .and_then(|s| s.strip_prefix("Bearer ")) + }) + .ok_or(AuthError::OidcMissingBearerToken)?; - let token_data = self.api_authorizer.check_auth(&token).await?; - let claims = token_data.claims; + let token_data = self.jwk_verifier.verify::(token).await?; + let claims = token_data.claims(); let sub = if let Some(sub) = claims.sub.as_deref() { sub } else { return Err(AuthError::OidcSubMissingError); }; - if !claims.contains_audience(&config.audience) { + if !claims.aud.iter().any(|aud| aud == &config.audience) { return Err(AuthError::OidcAudMissingError { aud: config.audience.clone(), }); } + let extra_claims = &claims.extra; if let Some(expected_scopes) = config.extra_scopes.as_ref() { - let found_scopes = claims.scopes().collect::>(); + let found_scopes = extra_claims.scopes().collect::>(); if !expected_scopes .iter() .all(|es| found_scopes.contains(es as &str)) { return Err(AuthError::OidcExtraScopesMatchError { expected: expected_scopes.iter().join(","), - found: claims.scope.unwrap_or_default(), + found: extra_claims + .scope + .as_deref() + .unwrap_or_default() + .to_string(), }); } } - if let Some(key) = config.extra_claim_key.as_ref() { - if !claims.has_claim(key) { - return Err(AuthError::OidcExtraClaimMissingError { claim: key.clone() }); - } - if let Some(value) = config.extra_claim_value.as_ref() - && claims.get_claim(key).is_none_or(|v| &v != value) - { - return Err(AuthError::OidcExtraClaimMatchError { - expected: value.clone(), - found: claims.get_claim(key).unwrap_or_default().to_string(), - key: key.clone(), - }); + if let Some(expected_extra_claims) = config.extra_claims.as_ref() { + for (expected_key, expected_value) in expected_extra_claims.iter() { + match (extra_claims.custom.get(expected_key), expected_value) { + (found_value, Some(expected_value)) => { + if let Some(Value::String(found_value)) = found_value + && expected_value == found_value + { + } else { + return Err(AuthError::OidcExtraClaimMatchError { + expected: expected_value.clone(), + found: found_value.map(|v| v.to_string()).unwrap_or_default(), + key: expected_key.clone(), + }); + } + } + (None, None) => { + return Err(AuthError::OidcExtraClaimMissingError { + claim: expected_key.clone(), + }); + } + _ => {} + } } } let subscriber_auth = match crate::models::auth::Model::find_by_pid(ctx, sub).await { diff --git a/apps/recorder/src/auth/service.rs b/apps/recorder/src/auth/service.rs index 2acec80..314349b 100644 --- a/apps/recorder/src/auth/service.rs +++ b/apps/recorder/src/auth/service.rs @@ -1,25 +1,22 @@ use std::{sync::Arc, time::Duration}; use async_trait::async_trait; -use axum::{ - extract::FromRequestParts, - http::request::Parts, - response::{IntoResponse as _, Response}, -}; +use axum::http::request::Parts; use fetch::{ HttpClient, HttpClientConfig, client::{HttpClientCacheBackendConfig, HttpClientCachePresetConfig}, }; use http::header::HeaderValue; -use jwt_authorizer::{JwtAuthorizer, Validation}; +use jwtk::jwk::RemoteJwksVerifier; use moka::future::Cache; +use openidconnect::{IssuerUrl, core::CoreProviderMetadata}; use snafu::prelude::*; use super::{ AuthConfig, basic::BasicAuthService, - errors::{AuthError, OidcProviderHttpClientSnafu}, - oidc::{OidcAuthClaims, OidcAuthService}, + errors::{AuthError, OidcProviderHttpClientSnafu, OidcProviderUrlSnafu}, + oidc::{OidcAuthService, OidcHttpClient}, }; use crate::{app::AppContextTrait, models::auth::AuthType}; @@ -29,22 +26,6 @@ pub struct AuthUserInfo { pub auth_type: AuthType, } -impl FromRequestParts> for AuthUserInfo { - type Rejection = Response; - - async fn from_request_parts( - parts: &mut Parts, - state: &Arc, - ) -> Result { - let auth_service = state.auth(); - - auth_service - .extract_user_info(state.as_ref(), parts) - .await - .map_err(|err| err.into_response()) - } -} - #[async_trait] pub trait AuthServiceTrait { async fn extract_user_info( @@ -66,27 +47,33 @@ impl AuthService { let result = match config { AuthConfig::Basic(config) => AuthService::Basic(Box::new(BasicAuthService { config })), AuthConfig::Oidc(config) => { - let validation = Validation::new() - .iss(&[&config.issuer]) - .aud(&[&config.audience]); + let oidc_provider_client = Arc::new( + HttpClient::from_config(HttpClientConfig { + exponential_backoff_max_retries: Some(3), + cache_backend: Some(HttpClientCacheBackendConfig::Moka { cache_size: 1 }), + cache_preset: Some(HttpClientCachePresetConfig::RFC7234), + ..Default::default() + }) + .context(OidcProviderHttpClientSnafu)?, + ); - let oidc_provider_client = HttpClient::from_config(HttpClientConfig { - exponential_backoff_max_retries: Some(3), - cache_backend: Some(HttpClientCacheBackendConfig::Moka { cache_size: 1 }), - cache_preset: Some(HttpClientCachePresetConfig::RFC7234), - ..Default::default() - }) - .context(OidcProviderHttpClientSnafu)?; + let provider_metadata = { + let client = OidcHttpClient(oidc_provider_client.clone()); + let issuer_url = + IssuerUrl::new(config.issuer.clone()).context(OidcProviderUrlSnafu)?; + CoreProviderMetadata::discover_async(issuer_url, &client).await + }?; - let api_authorizer = JwtAuthorizer::::from_oidc(&config.issuer) - .validation(validation) - .build() - .await?; + let jwk_verifier = RemoteJwksVerifier::new( + provider_metadata.jwks_uri().to_string().clone(), + None, + Duration::from_secs(300), + ); AuthService::Oidc(Box::new(OidcAuthService { config, - api_authorizer, - oidc_provider_client: Arc::new(oidc_provider_client), + jwk_verifier, + oidc_provider_client, oidc_request_cache: Cache::builder() .time_to_live(Duration::from_mins(5)) .name("oidc_request_cache") @@ -100,6 +87,7 @@ impl AuthService { #[async_trait] impl AuthServiceTrait for AuthService { + #[tracing::instrument(skip(self, ctx, request))] async fn extract_user_info( &self, ctx: &dyn AppContextTrait, diff --git a/apps/recorder/src/errors/app_error.rs b/apps/recorder/src/errors/app_error.rs index 487f978..aaa126f 100644 --- a/apps/recorder/src/errors/app_error.rs +++ b/apps/recorder/src/errors/app_error.rs @@ -47,7 +47,7 @@ pub enum RecorderError { #[snafu(transparent)] RSSError { source: rss::Error }, #[snafu(transparent)] - DotEnvError { source: dotenv::Error }, + DotEnvError { source: dotenvy::Error }, #[snafu(transparent)] TeraError { source: tera::Error }, #[snafu(transparent)] diff --git a/apps/recorder/src/graphql/infra/filter/json.rs b/apps/recorder/src/graphql/infra/filter/json.rs index 0775738..e0e5835 100644 --- a/apps/recorder/src/graphql/infra/filter/json.rs +++ b/apps/recorder/src/graphql/infra/filter/json.rs @@ -920,7 +920,7 @@ where pub fn register_jsonb_input_filter_to_dynamic_schema( schema_builder: SchemaBuilder, ) -> SchemaBuilder { - let json_filter_input_type = Scalar::new("JsonFilterInput"); + let json_filter_input_type = Scalar::new(JSONB_FILTER_NAME); schema_builder.register(json_filter_input_type) } @@ -1261,7 +1261,7 @@ mod tests { { "d": [ { - "$any": true + "$match": "$any" }, { "$eq": [1, 2, 3] diff --git a/apps/recorder/src/graphql/views/subscription.rs b/apps/recorder/src/graphql/views/subscription.rs index c18fade..597f5b8 100644 --- a/apps/recorder/src/graphql/views/subscription.rs +++ b/apps/recorder/src/graphql/views/subscription.rs @@ -52,7 +52,7 @@ impl SyncOneSubscriptionInfo { Object::new(Self::object_type_name()) .description("The output of the subscriptionSyncOne series of mutations") .field(Field::new( - "taskId", + SyncOneSubscriptionInfoFieldEnum::TaskId, TypeRef::named_nn(TypeRef::STRING), move |ctx| { FieldFuture::new(async move { diff --git a/apps/webui/src/infra/graphql/gql/gql.ts b/apps/webui/src/infra/graphql/gql/gql.ts index 28f6fe2..c6612e5 100644 --- a/apps/webui/src/infra/graphql/gql/gql.ts +++ b/apps/webui/src/infra/graphql/gql/gql.ts @@ -17,14 +17,14 @@ type Documents = { "\n query GetSubscriptions(\n $page: PageInput!,\n $filters: SubscriptionsFilterInput!,\n $orderBy: SubscriptionsOrderInput!\n) {\n subscriptions(\n pagination: {\n page: $page\n }\n filters: $filters\n orderBy: $orderBy\n ) {\n nodes {\n id\n createdAt\n updatedAt\n displayName\n category\n sourceUrl\n enabled\n }\n paginationInfo {\n total\n pages\n }\n }\n }\n": typeof types.GetSubscriptionsDocument, "\n mutation UpdateSubscriptions(\n $data: SubscriptionsUpdateInput!,\n $filters: SubscriptionsFilterInput!,\n ) {\n subscriptionsUpdate (\n data: $data\n filter: $filters\n ) {\n id\n createdAt\n updatedAt\n displayName\n category\n sourceUrl\n enabled\n }\n}\n": typeof types.UpdateSubscriptionsDocument, "\n mutation DeleteSubscriptions($filters: SubscriptionsFilterInput) {\n subscriptionsDelete(filter: $filters)\n }\n": typeof types.DeleteSubscriptionsDocument, - "\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filters: { id: {\n eq: $id\n } }) {\n nodes {\n id\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n rawName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n savePath\n deleted\n homepage\n }\n }\n }\n }\n}\n": typeof types.GetSubscriptionDetailDocument, + "\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filters: { id: {\n eq: $id\n } }) {\n nodes {\n id\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n rawName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n savePath\n homepage\n }\n }\n }\n }\n}\n": typeof types.GetSubscriptionDetailDocument, "\n mutation CreateSubscription($input: SubscriptionsInsertInput!) {\n subscriptionsCreateOne(data: $input) {\n id\n displayName\n sourceUrl\n enabled\n category\n }\n }\n": typeof types.CreateSubscriptionDocument, }; const documents: Documents = { "\n query GetSubscriptions(\n $page: PageInput!,\n $filters: SubscriptionsFilterInput!,\n $orderBy: SubscriptionsOrderInput!\n) {\n subscriptions(\n pagination: {\n page: $page\n }\n filters: $filters\n orderBy: $orderBy\n ) {\n nodes {\n id\n createdAt\n updatedAt\n displayName\n category\n sourceUrl\n enabled\n }\n paginationInfo {\n total\n pages\n }\n }\n }\n": types.GetSubscriptionsDocument, "\n mutation UpdateSubscriptions(\n $data: SubscriptionsUpdateInput!,\n $filters: SubscriptionsFilterInput!,\n ) {\n subscriptionsUpdate (\n data: $data\n filter: $filters\n ) {\n id\n createdAt\n updatedAt\n displayName\n category\n sourceUrl\n enabled\n }\n}\n": types.UpdateSubscriptionsDocument, "\n mutation DeleteSubscriptions($filters: SubscriptionsFilterInput) {\n subscriptionsDelete(filter: $filters)\n }\n": types.DeleteSubscriptionsDocument, - "\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filters: { id: {\n eq: $id\n } }) {\n nodes {\n id\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n rawName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n savePath\n deleted\n homepage\n }\n }\n }\n }\n}\n": types.GetSubscriptionDetailDocument, + "\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filters: { id: {\n eq: $id\n } }) {\n nodes {\n id\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n rawName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n savePath\n homepage\n }\n }\n }\n }\n}\n": types.GetSubscriptionDetailDocument, "\n mutation CreateSubscription($input: SubscriptionsInsertInput!) {\n subscriptionsCreateOne(data: $input) {\n id\n displayName\n sourceUrl\n enabled\n category\n }\n }\n": types.CreateSubscriptionDocument, }; @@ -57,7 +57,7 @@ export function gql(source: "\n mutation DeleteSubscriptions($filters: Subscr /** * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function gql(source: "\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filters: { id: {\n eq: $id\n } }) {\n nodes {\n id\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n rawName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n savePath\n deleted\n homepage\n }\n }\n }\n }\n}\n"): (typeof documents)["\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filters: { id: {\n eq: $id\n } }) {\n nodes {\n id\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n rawName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n savePath\n deleted\n homepage\n }\n }\n }\n }\n}\n"]; +export function gql(source: "\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filters: { id: {\n eq: $id\n } }) {\n nodes {\n id\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n rawName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n savePath\n homepage\n }\n }\n }\n }\n}\n"): (typeof documents)["\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filters: { id: {\n eq: $id\n } }) {\n nodes {\n id\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n rawName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n savePath\n homepage\n }\n }\n }\n }\n}\n"]; /** * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/apps/webui/src/infra/graphql/gql/graphql.ts b/apps/webui/src/infra/graphql/gql/graphql.ts index 3f8d73b..cb6c746 100644 --- a/apps/webui/src/infra/graphql/gql/graphql.ts +++ b/apps/webui/src/infra/graphql/gql/graphql.ts @@ -14,12 +14,12 @@ export type Scalars = { Boolean: { input: boolean; output: boolean; } Int: { input: number; output: number; } Float: { input: number; output: number; } + JsonbFilterInput: { input: any; output: any; } }; export type Bangumi = { __typename?: 'Bangumi'; createdAt: Scalars['String']['output']; - deleted: Scalars['Boolean']['output']; displayName: Scalars['String']['output']; episode: EpisodesConnection; fansub?: Maybe; @@ -64,7 +64,6 @@ export type BangumiSubscriptionBangumiArgs = { export type BangumiBasic = { __typename?: 'BangumiBasic'; createdAt: Scalars['String']['output']; - deleted: Scalars['Boolean']['output']; displayName: Scalars['String']['output']; fansub?: Maybe; homepage?: Maybe; @@ -98,7 +97,6 @@ export type BangumiEdge = { export type BangumiFilterInput = { and?: InputMaybe>; createdAt?: InputMaybe; - deleted?: InputMaybe; displayName?: InputMaybe; fansub?: InputMaybe; homepage?: InputMaybe; @@ -118,7 +116,6 @@ export type BangumiFilterInput = { export type BangumiInsertInput = { createdAt?: InputMaybe; - deleted: Scalars['Boolean']['input']; displayName: Scalars['String']['input']; fansub?: InputMaybe; homepage?: InputMaybe; @@ -136,7 +133,6 @@ export type BangumiInsertInput = { export type BangumiOrderInput = { createdAt?: InputMaybe; - deleted?: InputMaybe; displayName?: InputMaybe; extra?: InputMaybe; fansub?: InputMaybe; @@ -157,7 +153,6 @@ export type BangumiOrderInput = { export type BangumiUpdateInput = { createdAt?: InputMaybe; - deleted?: InputMaybe; displayName?: InputMaybe; fansub?: InputMaybe; homepage?: InputMaybe; @@ -478,7 +473,6 @@ export type Episodes = { bangumi?: Maybe; bangumiId: Scalars['Int']['output']; createdAt: Scalars['String']['output']; - deleted: Scalars['Boolean']['output']; displayName: Scalars['String']['output']; download: SubscriptionsConnection; episodeIndex: Scalars['Int']['output']; @@ -526,7 +520,6 @@ export type EpisodesBasic = { __typename?: 'EpisodesBasic'; bangumiId: Scalars['Int']['output']; createdAt: Scalars['String']['output']; - deleted: Scalars['Boolean']['output']; displayName: Scalars['String']['output']; episodeIndex: Scalars['Int']['output']; fansub?: Maybe; @@ -563,7 +556,6 @@ export type EpisodesFilterInput = { and?: InputMaybe>; bangumiId?: InputMaybe; createdAt?: InputMaybe; - deleted?: InputMaybe; displayName?: InputMaybe; episodeIndex?: InputMaybe; fansub?: InputMaybe; @@ -586,7 +578,6 @@ export type EpisodesFilterInput = { export type EpisodesInsertInput = { bangumiId: Scalars['Int']['input']; createdAt?: InputMaybe; - deleted: Scalars['Boolean']['input']; displayName: Scalars['String']['input']; episodeIndex: Scalars['Int']['input']; fansub?: InputMaybe; @@ -607,7 +598,6 @@ export type EpisodesInsertInput = { export type EpisodesOrderInput = { bangumiId?: InputMaybe; createdAt?: InputMaybe; - deleted?: InputMaybe; displayName?: InputMaybe; episodeIndex?: InputMaybe; extra?: InputMaybe; @@ -630,7 +620,6 @@ export type EpisodesOrderInput = { export type EpisodesUpdateInput = { bangumiId?: InputMaybe; createdAt?: InputMaybe; - deleted?: InputMaybe; displayName?: InputMaybe; episodeIndex?: InputMaybe; fansub?: InputMaybe; @@ -682,6 +671,10 @@ export type Mutation = { episodesCreateOne: EpisodesBasic; episodesDelete: Scalars['Int']['output']; episodesUpdate: Array; + subscriberTasksCreateBatch: Array; + subscriberTasksCreateOne: SubscriberTasksBasic; + subscriberTasksDelete: Scalars['Int']['output']; + subscriberTasksUpdate: Array; subscriptionBangumiCreateBatch: Array; subscriptionBangumiCreateOne: SubscriptionBangumiBasic; subscriptionBangumiDelete: Scalars['Int']['output']; @@ -690,6 +683,7 @@ export type Mutation = { subscriptionEpisodeCreateOne: SubscriptionEpisodeBasic; subscriptionEpisodeDelete: Scalars['Int']['output']; subscriptionEpisodeUpdate: Array; + subscriptionSyncOneSources: SyncOneSubscriptionInfo; subscriptionsCreateBatch: Array; subscriptionsCreateOne: SubscriptionsBasic; subscriptionsDelete: Scalars['Int']['output']; @@ -781,6 +775,27 @@ export type MutationEpisodesUpdateArgs = { }; +export type MutationSubscriberTasksCreateBatchArgs = { + data: Array; +}; + + +export type MutationSubscriberTasksCreateOneArgs = { + data: SubscriberTasksInsertInput; +}; + + +export type MutationSubscriberTasksDeleteArgs = { + filter?: InputMaybe; +}; + + +export type MutationSubscriberTasksUpdateArgs = { + data: SubscriberTasksUpdateInput; + filter?: InputMaybe; +}; + + export type MutationSubscriptionBangumiCreateBatchArgs = { data: Array; }; @@ -823,6 +838,11 @@ export type MutationSubscriptionEpisodeUpdateArgs = { }; +export type MutationSubscriptionSyncOneSourcesArgs = { + filter: SyncOneSubscriptionFilterInput; +}; + + export type MutationSubscriptionsCreateBatchArgs = { data: Array; }; @@ -887,9 +907,12 @@ export type Query = { downloaders: DownloadersConnection; downloads: DownloadsConnection; episodes: EpisodesConnection; + subscriberTasks: SubscriberTasksConnection; subscribers: SubscribersConnection; subscriptionBangumi: SubscriptionBangumiConnection; subscriptionEpisode: SubscriptionEpisodeConnection; + subscriptionSyncOneFeedsFull: SyncOneSubscriptionInfo; + subscriptionSyncOneFeedsIncremental: SyncOneSubscriptionInfo; subscriptions: SubscriptionsConnection; }; @@ -927,6 +950,13 @@ export type QueryEpisodesArgs = { }; +export type QuerySubscriberTasksArgs = { + filters?: InputMaybe; + orderBy?: InputMaybe; + pagination?: InputMaybe; +}; + + export type QuerySubscribersArgs = { filters?: InputMaybe; orderBy?: InputMaybe; @@ -948,6 +978,16 @@ export type QuerySubscriptionEpisodeArgs = { }; +export type QuerySubscriptionSyncOneFeedsFullArgs = { + filter: SyncOneSubscriptionFilterInput; +}; + + +export type QuerySubscriptionSyncOneFeedsIncrementalArgs = { + filter: SyncOneSubscriptionFilterInput; +}; + + export type QuerySubscriptionsArgs = { filters?: InputMaybe; orderBy?: InputMaybe; @@ -978,6 +1018,109 @@ export type SubscriberIdFilterInput = { eq?: InputMaybe; }; +export type SubscriberTasks = { + __typename?: 'SubscriberTasks'; + attempts: Scalars['Int']['output']; + doneAt?: Maybe; + id: Scalars['String']['output']; + lastError?: Maybe; + lockAt?: Maybe; + lockBy?: Maybe; + maxAttempts: Scalars['Int']['output']; + priority: Scalars['Int']['output']; + runAt: Scalars['String']['output']; + status: Scalars['String']['output']; + subscriber?: Maybe; + subscriberId: Scalars['Int']['output']; +}; + +export type SubscriberTasksBasic = { + __typename?: 'SubscriberTasksBasic'; + attempts: Scalars['Int']['output']; + doneAt?: Maybe; + id: Scalars['String']['output']; + lastError?: Maybe; + lockAt?: Maybe; + lockBy?: Maybe; + maxAttempts: Scalars['Int']['output']; + priority: Scalars['Int']['output']; + runAt: Scalars['String']['output']; + status: Scalars['String']['output']; + subscriberId: Scalars['Int']['output']; +}; + +export type SubscriberTasksConnection = { + __typename?: 'SubscriberTasksConnection'; + edges: Array; + nodes: Array; + pageInfo: PageInfo; + paginationInfo?: Maybe; +}; + +export type SubscriberTasksEdge = { + __typename?: 'SubscriberTasksEdge'; + cursor: Scalars['String']['output']; + node: SubscriberTasks; +}; + +export type SubscriberTasksFilterInput = { + and?: InputMaybe>; + attempts?: InputMaybe; + doneAt?: InputMaybe; + id?: InputMaybe; + job?: InputMaybe; + lastError?: InputMaybe; + lockAt?: InputMaybe; + lockBy?: InputMaybe; + maxAttempts?: InputMaybe; + or?: InputMaybe>; + priority?: InputMaybe; + runAt?: InputMaybe; + status?: InputMaybe; + subscriberId?: InputMaybe; +}; + +export type SubscriberTasksInsertInput = { + attempts: Scalars['Int']['input']; + doneAt?: InputMaybe; + id?: InputMaybe; + lastError?: InputMaybe; + lockAt?: InputMaybe; + lockBy?: InputMaybe; + maxAttempts: Scalars['Int']['input']; + priority: Scalars['Int']['input']; + runAt: Scalars['String']['input']; + status: Scalars['String']['input']; +}; + +export type SubscriberTasksOrderInput = { + attempts?: InputMaybe; + doneAt?: InputMaybe; + id?: InputMaybe; + job?: InputMaybe; + lastError?: InputMaybe; + lockAt?: InputMaybe; + lockBy?: InputMaybe; + maxAttempts?: InputMaybe; + priority?: InputMaybe; + runAt?: InputMaybe; + status?: InputMaybe; + subscriberId?: InputMaybe; +}; + +export type SubscriberTasksUpdateInput = { + attempts?: InputMaybe; + doneAt?: InputMaybe; + id?: InputMaybe; + lastError?: InputMaybe; + lockAt?: InputMaybe; + lockBy?: InputMaybe; + maxAttempts?: InputMaybe; + priority?: InputMaybe; + runAt?: InputMaybe; + status?: InputMaybe; +}; + export type Subscribers = { __typename?: 'Subscribers'; bangumi: BangumiConnection; @@ -1051,6 +1194,7 @@ export type SubscriptionBangumi = { bangumi?: Maybe; bangumiId: Scalars['Int']['output']; id: Scalars['Int']['output']; + subscriber?: Maybe; subscriberId: Scalars['Int']['output']; subscription?: Maybe; subscriptionId: Scalars['Int']['output']; @@ -1108,7 +1252,9 @@ export type SubscriptionBangumiUpdateInput = { export enum SubscriptionCategoryEnum { Manual = 'manual', - Mikan = 'mikan' + MikanBangumi = 'mikan_bangumi', + MikanSeason = 'mikan_season', + MikanSubscriber = 'mikan_subscriber' } export type SubscriptionCategoryEnumFilterInput = { @@ -1129,6 +1275,7 @@ export type SubscriptionEpisode = { episode?: Maybe; episodeId: Scalars['Int']['output']; id: Scalars['Int']['output']; + subscriber?: Maybe; subscriberId: Scalars['Int']['output']; subscription?: Maybe; subscriptionId: Scalars['Int']['output']; @@ -1305,6 +1452,17 @@ export type SubscriptionsUpdateInput = { updatedAt?: InputMaybe; }; +/** The input of the subscriptionSyncOne series of mutations */ +export type SyncOneSubscriptionFilterInput = { + subscriptionId: Scalars['Int']['input']; +}; + +/** The output of the subscriptionSyncOne series of mutations */ +export type SyncOneSubscriptionInfo = { + __typename?: 'SyncOneSubscriptionInfo'; + taskId: Scalars['String']['output']; +}; + export type TextFilterInput = { between?: InputMaybe>; eq?: InputMaybe; @@ -1349,7 +1507,7 @@ export type GetSubscriptionDetailQueryVariables = Exact<{ }>; -export type GetSubscriptionDetailQuery = { __typename?: 'Query', subscriptions: { __typename?: 'SubscriptionsConnection', nodes: Array<{ __typename?: 'Subscriptions', id: number, displayName: string, createdAt: string, updatedAt: string, category: SubscriptionCategoryEnum, sourceUrl: string, enabled: boolean, bangumi: { __typename?: 'BangumiConnection', nodes: Array<{ __typename?: 'Bangumi', createdAt: string, updatedAt: string, id: number, mikanBangumiId?: string | null, displayName: string, rawName: string, season: number, seasonRaw?: string | null, fansub?: string | null, mikanFansubId?: string | null, rssLink?: string | null, posterLink?: string | null, savePath?: string | null, deleted: boolean, homepage?: string | null }> } }> } }; +export type GetSubscriptionDetailQuery = { __typename?: 'Query', subscriptions: { __typename?: 'SubscriptionsConnection', nodes: Array<{ __typename?: 'Subscriptions', id: number, displayName: string, createdAt: string, updatedAt: string, category: SubscriptionCategoryEnum, sourceUrl: string, enabled: boolean, bangumi: { __typename?: 'BangumiConnection', nodes: Array<{ __typename?: 'Bangumi', createdAt: string, updatedAt: string, id: number, mikanBangumiId?: string | null, displayName: string, rawName: string, season: number, seasonRaw?: string | null, fansub?: string | null, mikanFansubId?: string | null, rssLink?: string | null, posterLink?: string | null, savePath?: string | null, homepage?: string | null }> } }> } }; export type CreateSubscriptionMutationVariables = Exact<{ input: SubscriptionsInsertInput; @@ -1362,5 +1520,5 @@ export type CreateSubscriptionMutation = { __typename?: 'Mutation', subscription export const GetSubscriptionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSubscriptions"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"page"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"PageInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsFilterInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsOrderInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"pagination"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"page"},"value":{"kind":"Variable","name":{"kind":"Name","value":"page"}}}]}},{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}},{"kind":"Argument","name":{"kind":"Name","value":"orderBy"},"value":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"nodes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrl"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}}]}},{"kind":"Field","name":{"kind":"Name","value":"paginationInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"total"}},{"kind":"Field","name":{"kind":"Name","value":"pages"}}]}}]}}]}}]} as unknown as DocumentNode; export const UpdateSubscriptionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateSubscriptions"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsUpdateInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsFilterInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptionsUpdate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrl"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}}]}}]}}]} as unknown as DocumentNode; export const DeleteSubscriptionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteSubscriptions"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsFilterInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptionsDelete"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}}]}]}}]} as unknown as DocumentNode; -export const GetSubscriptionDetailDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSubscriptionDetail"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}]}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"nodes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrl"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"bangumi"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"nodes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"mikanBangumiId"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"rawName"}},{"kind":"Field","name":{"kind":"Name","value":"season"}},{"kind":"Field","name":{"kind":"Name","value":"seasonRaw"}},{"kind":"Field","name":{"kind":"Name","value":"fansub"}},{"kind":"Field","name":{"kind":"Name","value":"mikanFansubId"}},{"kind":"Field","name":{"kind":"Name","value":"rssLink"}},{"kind":"Field","name":{"kind":"Name","value":"posterLink"}},{"kind":"Field","name":{"kind":"Name","value":"savePath"}},{"kind":"Field","name":{"kind":"Name","value":"deleted"}},{"kind":"Field","name":{"kind":"Name","value":"homepage"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode; +export const GetSubscriptionDetailDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSubscriptionDetail"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}]}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"nodes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrl"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"bangumi"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"nodes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"mikanBangumiId"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"rawName"}},{"kind":"Field","name":{"kind":"Name","value":"season"}},{"kind":"Field","name":{"kind":"Name","value":"seasonRaw"}},{"kind":"Field","name":{"kind":"Name","value":"fansub"}},{"kind":"Field","name":{"kind":"Name","value":"mikanFansubId"}},{"kind":"Field","name":{"kind":"Name","value":"rssLink"}},{"kind":"Field","name":{"kind":"Name","value":"posterLink"}},{"kind":"Field","name":{"kind":"Name","value":"savePath"}},{"kind":"Field","name":{"kind":"Name","value":"homepage"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const CreateSubscriptionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateSubscription"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsInsertInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptionsCreateOne"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrl"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"category"}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file diff --git a/packages/downloader/Cargo.toml b/packages/downloader/Cargo.toml index 5fb8017..8487c89 100644 --- a/packages/downloader/Cargo.toml +++ b/packages/downloader/Cargo.toml @@ -35,8 +35,11 @@ qbit-rs = { git = "https://github.com/lonelyhentxi/qbit.git", rev = "72d53138ebe "builder", ] } merge-struct = "0.1" -librqbit-core = "4" -librqbit = { version = "8", features = ["async-bt", "watch"] } +librqbit-core = { git = "https://github.com/ikatson/rqbit.git", rev = "0936730" } +librqbit = { git = "https://github.com/ikatson/rqbit.git", rev = "0936730", features = [ + "async-bt", + "watch", +] } util = { workspace = true } testing-torrents = { workspace = true, optional = true } diff --git a/packages/util-derive/src/lib.rs b/packages/util-derive/src/lib.rs index 387b12c..46daf04 100644 --- a/packages/util-derive/src/lib.rs +++ b/packages/util-derive/src/lib.rs @@ -128,6 +128,12 @@ impl DynamicGraphqlInfo { } } + impl From<#enum_name> for String { + fn from(value: #enum_name) -> Self { + value.as_str().to_string() + } + } + impl std::str::FromStr for #enum_name { type Err = String;