diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ff016f739..a61ddbe65 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,7 +37,6 @@ jobs: PKG_DIR=../client make -C securedrop-builder requirements PKG_DIR=../export make -C securedrop-builder requirements PKG_DIR=../log make -C securedrop-builder requirements - PKG_DIR=../proxy make -C securedrop-builder requirements git config --global --add safe.directory "$GITHUB_WORKSPACE" git diff --ignore-matching-lines=# --exit-code diff --git a/.github/workflows/sdk.yml b/.github/workflows/sdk.yml index 55249286b..afd8feb7f 100644 --- a/.github/workflows/sdk.yml +++ b/.github/workflows/sdk.yml @@ -29,6 +29,9 @@ jobs: wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz && tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz + - name: Build proxy + run: | + cargo build - name: Run tests without VCR cassettes run: | # Start the server in the background @@ -38,5 +41,4 @@ jobs: # Wait for server to come up dockerize -wait http://127.0.0.1:8080 -timeout 5m # Run tests - rm client/tests/sdk/data/*.yml - make -C client test-sdk + make -C client regenerate-sdk-cassettes diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d29e7c61f..2c0ba6bdc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,18 +22,18 @@ jobs: debian_version: - bullseye - bookworm - # bookworm jobs are failing and will be - # replaced with proxy v2 shortly, so skip - # https://github.com/freedomofpress/securedrop-client/issues/1681 - exclude: - - component: proxy - debian_version: bookworm runs-on: ubuntu-latest container: debian:${{ matrix.debian_version }} steps: - run: | apt-get update && apt-get install --yes git make gnupg + - name: Install Rust-specific dependencies + run: apt-get install --yes build-essential curl libssl-dev pkg-config + if: ${{ matrix.component == 'proxy' }} - uses: actions/checkout@v4 + # Install Rust 1.74.1, keep in sync with rust-toolchain.toml + - uses: dtolnay/rust-toolchain@aec8960fc037f3ba5dd7773fd5b938a0ab22c50f + if: ${{ matrix.component == 'proxy' }} - name: Install dependencies run: | source /etc/os-release diff --git a/Cargo.lock b/Cargo.lock index af3bb1ddc..ba64dc3ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,1370 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + +[[package]] +name = "async-compression" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a116f46a969224200a0a97f29cfd4c50e7534e4b4826bd23ea2c3c533039c82c" +dependencies = [ + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags 2.4.2", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang-sys" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "crc32fast" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "h2" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "http" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[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 = "indexmap" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "js-sys" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libloading" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "openssl" +version = "0.10.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15c9d69dd87a29568d4d017cfe8ec518706046a05184e5aea92d0af890b803c8" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e1bf214306098e4832460f797824c05d25aacdf896f64a985fb0fd992454ae" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" + +[[package]] +name = "prettyplease" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "reqwest" +version = "0.11.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" +dependencies = [ + "async-compression", + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "winreg", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +dependencies = [ + "bitflags 2.4.2", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + +[[package]] +name = "ryu" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "securedrop-proxy" version = "0.1.0" +dependencies = [ + "anyhow", + "bindgen", + "futures-util", + "reqwest", + "serde", + "serde_json", + "tokio", + "url", +] + +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.113" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "socket2" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" + +[[package]] +name = "wasm-streams" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "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.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.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.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.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.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.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.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 = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] diff --git a/client/Makefile b/client/Makefile index 346277f12..0a86d6ba6 100644 --- a/client/Makefile +++ b/client/Makefile @@ -85,6 +85,14 @@ test-functional: ## Run the functional tests test-sdk: ## Run just the sdk tests @poetry run pytest -v $(STESTS) +.PHONY: regenerate-sdk-cassettes +regenerate-sdk-cassettes: + @echo "Checking if a development server is available to regenerate cassettes..." + @echo "NB. It should be a fresh development server via \"make dev\", with no other data! HTTP requests and responses will be recorded unredacted, including credentials and tokens." + @curl http://localhost:8080/metadata + @rm -fr tests/sdk/data/ + @make test-sdk + .PHONY: flake8 flake8: ## Run flake8 linting @poetry run flake8 securedrop_client tests diff --git a/client/README.md b/client/README.md index 0e3730190..17334ae69 100644 --- a/client/README.md +++ b/client/README.md @@ -368,9 +368,9 @@ We use `qtbot`, bundled with the [pytest-qt](https://pytest-qt.readthedocs.io/en #### Generating new cassettes -We use [vcrpy](https://vcrpy.readthedocs.io/en/latest/) to record and replay API calls. Each request made from a test and response from the server is stored in a "cassette" yaml file in the `tests/functional/cassettes` directory. +We use [vcrpy](https://vcrpy.readthedocs.io/en/latest/) to record and replay API calls. Each request made from a test and response from the server is stored in a "cassette" yaml file in the `tests/functional/data` directory. -If the SDK changes its API, then you'll see the following warning indicating that a request failed to be found in an existing cassette and that you'll need to regenerate cassettes: +If the server changes its API, then you'll see the following warning indicating that a request failed to be found in an existing cassette and that you'll need to regenerate cassettes: ``` Can't overwrite existing cassette ('') in your current record mode ('once'). @@ -378,9 +378,23 @@ Can't overwrite existing cassette ('') i To set up a local dev server and generate cassettes, follow these steps: -1. Bypass TOTP verification so that we can use the TOTP value of `123456` hard-coded in `tests/conftest.py`. You can do this by applying the following patch to the server code: +1. Disable one TOTP check so that we can re-use the same one-time-code. You can do this by applying the following patch to the server code: -https://gist.github.com/creviera/8793d5ec4d28f034f2c1e8320a93866a + ``` + diff --git a/securedrop/models.py b/securedrop/models.py + index e70e492fc..bdbc55a06 100644 + --- a/securedrop/models.py + +++ b/securedrop/models.py + @@ -645,7 +645,7 @@ class Journalist(db.Model): + + # Reject OTP tokens that have already been used + if self.last_token is not None and self.last_token == sanitized_token: + - raise two_factor.OtpTokenInvalid("Token already used") + + pass + + if self.is_totp: + # TOTP + ``` 2. Start the server in a docker container and add 5 sources with messages, files, and replies by running: @@ -391,7 +405,7 @@ https://gist.github.com/creviera/8793d5ec4d28f034f2c1e8320a93866a 3. Delete the cassettes you wish to regenerate or just delete the entire directory by running: ```bash - rm -r tests/functional/cassettes + rm -r tests/functional/data ``` 4. Regenerate cassettes by running: diff --git a/client/build-requirements.txt b/client/build-requirements.txt index 39f6d443d..9a60f3e82 100644 --- a/client/build-requirements.txt +++ b/client/build-requirements.txt @@ -1,14 +1,9 @@ alembic==1.1.0 --hash=sha256:5908bd669bc67bd8ee143150fd9d21205d7f9c36e87587e06370639138af4d01 arrow==0.12.1 --hash=sha256:e2742eb33011f7aff1d5f27501d802680b6627939f20ff2ef56f050c14af59fa -certifi==2023.7.22 --hash=sha256:920fc822272317b0d13e60eef0405ddd7f921e08dd21150a9eb613c863e31c2a -charset-normalizer==2.0.4 --hash=sha256:cd9a4492eef4e5276c07f9c0dc1338e7be3e95f2a536bf2c5b620b1f27d03d74 -idna==3.2 --hash=sha256:691d9fc304505c65ea9ceb8eb7385d63988e344c065cacbbd2156ff9bdfcf0c1 jinja2==3.1.3 --hash=sha256:764740680cf22a4a0b5d5dae8006fd5468310da0e81a6899d349cc4a44a0315f mako==1.2.2 --hash=sha256:f61384bcc80318821d1116891a82bb0ff18a9a4035c7c4eff72aced45ab590b5 markupsafe==2.0.1 --hash=sha256:e61445980f0dcd584d728844d8ad516c9e460bd71f53c14c0269d73de6fba6be --hash=sha256:9a055a175f351a559937fb80ebb2885d005283577a016c0139817e261fb759eb python-dateutil==2.7.5 --hash=sha256:2961735b604e5165d923a4e39b9bcbde6a4c363f257f5477b6339459fd7c1679 python-editor==1.0.3 --hash=sha256:42e5b2a7583cd278dff00ae1fc6b8b735da0502ceeb0914991eaaf5f91ac84ac -requests==2.31.0 --hash=sha256:9f7f0f507fe7a9e10ea51e666da60aafcfcda94c71f0cac477dbadd8d25de49f six==1.11.0 --hash=sha256:eb52689b06ca7433c1cac3b91f320400bd3b358790b7ff4b6367cb1c81d37561 sqlalchemy==1.3.3 --hash=sha256:af3ec7384a7da692a0db1b807da2eb5bda1372a1eea2a8b26c2ff8ccc1bbf897 --hash=sha256:86ed1e4985a9fd4f3c784da1fcefb89f4435c1c70815f43e5741c0c9f3c79be3 -urllib3==1.26.6 --hash=sha256:7a2814749409a681ab58babe6539b02a2f84f6649904211f90fb649811ae7b36 diff --git a/client/poetry.lock b/client/poetry.lock index cb9995373..15f5f76fc 100644 --- a/client/poetry.lock +++ b/client/poetry.lock @@ -1400,21 +1400,6 @@ files = [ [package.dependencies] pytest = ">=3.0.0" -[[package]] -name = "pytest-vcr" -version = "1.0.2" -description = "Plugin for managing VCR.py cassettes" -optional = false -python-versions = "*" -files = [ - {file = "pytest-vcr-1.0.2.tar.gz", hash = "sha256:23ee51b75abbcc43d926272773aae4f39f93aceb75ed56852d0bf618f92e1896"}, - {file = "pytest_vcr-1.0.2-py2.py3-none-any.whl", hash = "sha256:2f316e0539399bea0296e8b8401145c62b6f85e9066af7e57b6151481b0d6d9c"}, -] - -[package.dependencies] -pytest = ">=3.6.0" -vcrpy = "*" - [[package]] name = "python-dateutil" version = "2.7.5" @@ -1916,20 +1901,6 @@ files = [ {file = "types_python_dateutil-2.8.19.14-py3-none-any.whl", hash = "sha256:f977b8de27787639986b4e28963263fd0e5158942b3ecef91b9335c130cb1ce9"}, ] -[[package]] -name = "types-requests" -version = "2.31.0.6" -description = "Typing stubs for requests" -optional = false -python-versions = ">=3.7" -files = [ - {file = "types-requests-2.31.0.6.tar.gz", hash = "sha256:cd74ce3b53c461f1228a9b783929ac73a666658f223e28ed29753771477b3bd0"}, - {file = "types_requests-2.31.0.6-py3-none-any.whl", hash = "sha256:a2db9cb228a81da8348b49ad6db3f5519452dd20a9c1e1a868c83c5fe88fd1a9"}, -] - -[package.dependencies] -types-urllib3 = "*" - [[package]] name = "types-setuptools" version = "68.2.0.0" @@ -1941,17 +1912,6 @@ files = [ {file = "types_setuptools-68.2.0.0-py3-none-any.whl", hash = "sha256:77edcc843e53f8fc83bb1a840684841f3dc804ec94562623bfa2ea70d5a2ba1b"}, ] -[[package]] -name = "types-urllib3" -version = "1.26.25.14" -description = "Typing stubs for urllib3" -optional = false -python-versions = "*" -files = [ - {file = "types-urllib3-1.26.25.14.tar.gz", hash = "sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f"}, - {file = "types_urllib3-1.26.25.14-py3-none-any.whl", hash = "sha256:9683bbb7fb72e32bfe9d2be6e04875fbe1b3eeec3cbb4ea231435aa7fd6b4f0e"}, -] - [[package]] name = "typing-extensions" version = "4.8.0" @@ -2184,4 +2144,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "3f1aa5fc1f7b2b0d72b56a6e5a505ab68294a1b4d82562ecb8e12fe67dabe2e5" +content-hash = "1e4e90373506405c84720ed7d7f6a1aa28acad6155a42ce4c9a48b7c480e5695" diff --git a/client/pyproject.toml b/client/pyproject.toml index 75908eff0..a24638e88 100644 --- a/client/pyproject.toml +++ b/client/pyproject.toml @@ -13,7 +13,6 @@ SQLAlchemy = "^1.3.3" alembic = "^1.1.0" arrow = "^0.12.1" python-dateutil = "^2.7.5" -requests = "^2.31.0" [tool.poetry.group.dev.dependencies] # In production these two are installed using a system package @@ -40,10 +39,9 @@ pytest-cov = "*" pytest-mock = "*" pytest-qt = "^4.2.0" pytest-random-order = "*" -pytest-vcr = "*" semgrep = "*" translate-toolkit = "*" types-polib = "*" types-python-dateutil = "*" -types-requests = "^2.31.0" types-setuptools = "^68.0.0" +vcrpy = "^5.1.0" diff --git a/client/run.sh b/client/run.sh index 5a62ba629..f23769aff 100755 --- a/client/run.sh +++ b/client/run.sh @@ -39,7 +39,10 @@ echo "" cleanup -gpg --allow-secret-key-import --import tests/files/securedrop.gpg.asc & +gpg --allow-secret-key-import --import tests/files/securedrop.gpg.asc + +echo "Building proxy..." +(cd ../proxy && cargo build) # create the database and config for local testing poetry run python create_dev_data.py "$SDC_HOME" & diff --git a/client/securedrop_client/sdk/__init__.py b/client/securedrop_client/sdk/__init__.py index 9849a2634..7281b4098 100644 --- a/client/securedrop_client/sdk/__init__.py +++ b/client/securedrop_client/sdk/__init__.py @@ -2,13 +2,11 @@ import http import json import os +import subprocess +from dataclasses import dataclass from datetime import datetime # noqa: F401 -from subprocess import PIPE, Popen, TimeoutExpired -from typing import Any, Dict, List, Optional, Tuple -from urllib.parse import urljoin - -import requests -from requests.exceptions import ConnectionError, ConnectTimeout, ReadTimeout, TooManyRedirects +from pathlib import Path +from typing import Any, Dict, List, Optional, Tuple, Union from .sdlocalobjects import ( AuthError, @@ -45,31 +43,18 @@ def __init__(self) -> None: super().__init__("Cannot connect to the server.") -def json_query(proxy_vm_name: str, data: str, timeout: Optional[int] = None) -> str: - """ - Takes a JSON based query and passes it to the network proxy. - Returns the JSON output from the proxy. - """ - p = Popen( - ["/usr/lib/qubes/qrexec-client-vm", proxy_vm_name, "securedrop.Proxy"], - stdin=PIPE, - stdout=PIPE, - stderr=PIPE, - ) - if p.stdin is not None: - p.stdin.write(data.encode("utf-8")) - - try: - stdout, _ = p.communicate(timeout=timeout) # type: (bytes, bytes) - except TimeoutExpired: - try: - p.terminate() - except Exception: - pass - raise RequestTimeoutError - else: - output = stdout.decode("utf-8") - return output.strip() +@dataclass(frozen=True) +class StreamedResponse: + contents: bytes + sha256sum: str + filename: str + + +@dataclass(frozen=True) +class JSONResponse: + data: dict + status: int + headers: Dict[str, str] class API: @@ -109,7 +94,7 @@ def __init__( self.first_name = None # type: Optional[str] self.last_name = None # type: Optional[str] self.req_headers = dict() # type: Dict[str, str] - self.proxy = proxy # type: bool + self.development_mode = not proxy # type: bool self.default_request_timeout = default_request_timeout or DEFAULT_REQUEST_TIMEOUT self.default_download_timeout = default_download_timeout or DEFAULT_DOWNLOAD_TIMEOUT @@ -122,102 +107,96 @@ def __init__( except Exception: pass # We already have a default name - def _send_json_request( - self, - method: str, - path_query: str, - body: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - timeout: Optional[int] = None, - ) -> Tuple[Any, int, Dict[str, str]]: - if self.proxy: # We are using the Qubes securedrop-proxy - func = self._send_rpc_json_request - else: # We are not using the Qubes securedrop-proxy - func = self._send_http_json_request - - return func(method, path_query, body, headers, timeout) - - def _send_http_json_request( - self, - method: str, - path_query: str, - body: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - timeout: Optional[int] = None, - ) -> Tuple[Any, int, Dict[str, str]]: - url = urljoin(self.server, path_query) - kwargs = {"headers": headers} # type: Dict[str, Any] - - if timeout: - kwargs["timeout"] = timeout - - if method == "POST": - kwargs["data"] = body - - try: - result = requests.request(method, url, **kwargs) - except (ConnectTimeout, ReadTimeout): - raise RequestTimeoutError - except (TooManyRedirects, ConnectionError): - raise ServerConnectionError + def _rpc_target(self) -> List: + if not self.development_mode: + return ["/usr/lib/qubes/qrexec-client-vm", self.proxy_vm_name, "securedrop.Proxy"] + # Development mode, find the target directory and look for a debug securedrop-proxy + # binary. We assume that `cargo build` has already been run. We don't use `cargo run` + # because it adds its own output that would interfere with ours. + target_directory = json.loads( + subprocess.check_output(["cargo", "metadata", "--format-version", "1"], text=True) + )["target_directory"] + return [f"{target_directory}/debug/securedrop-proxy"] - if result.status_code == http.HTTPStatus.FORBIDDEN: - raise AuthError("forbidden") - - # Because when we download a file there is no JSON in the body - if path_query.endswith("/download"): - return result, result.status_code, dict(result.headers) - - return result.json(), result.status_code, dict(result.headers) - - def _send_rpc_json_request( + def _send_json_request( self, method: str, path_query: str, + stream: bool = False, body: Optional[str] = None, headers: Optional[Dict[str, str]] = None, timeout: Optional[int] = None, - ) -> Tuple[Any, int, Dict[str, str]]: - data = {"method": method, "path_query": path_query} # type: Dict[str, Any] + ) -> Union[StreamedResponse, JSONResponse]: + data: Dict[str, Any] = {"method": method, "path_query": path_query, "stream": stream} - if method == "POST": + if method == "POST" and body: data["body"] = body - if headers is not None and headers: + if headers: data["headers"] = headers if timeout: data["timeout"] = timeout - data_str = json.dumps(data) - - json_result = json_query(self.proxy_vm_name, data_str, timeout) - if not json_result: - raise BaseError("No response from proxy") + data_str = json.dumps(data).encode() try: - result = json.loads(json_result) - except json.decoder.JSONDecodeError: - raise BaseError("Error in parsing JSON") + env = {} + if self.development_mode: + env["SD_PROXY_ORIGIN"] = self.server + response = subprocess.run( + self._rpc_target(), capture_output=True, timeout=timeout, input=data_str, env=env + ) + except subprocess.TimeoutExpired as err: + raise RequestTimeoutError from err + + # error handling + if response.returncode != 0: + try: + error = json.loads(response.stderr.decode()) + except json.decoder.JSONDecodeError as err: + raise BaseError("Unable to parse stderr JSON") from err + raise BaseError("Internal proxy error: " + error.get("error", "unknown error")) + + # We need to peek at the content to see if we got a streaming response, + # which only happens for stream=True and non-error response + if stream and response.stdout[0] != b"{": + try: + stderr = json.loads(response.stderr.decode()) + sha256sum = stderr["headers"]["etag"] + filename = stderr["headers"]["content-disposition"] + except (json.decoder.JSONDecodeError, KeyError) as err: + raise BaseError("Unable to parse header metadata from response") from err + # Get the checksum out of stderr + return StreamedResponse( + contents=response.stdout, sha256sum=sha256sum, filename=filename + ) - data = json.loads(result["body"]) + try: + result = json.loads(response.stdout.decode()) + except json.decoder.JSONDecodeError as err: + raise BaseError("Unable to parse stdout JSON") from err - if "error" in data and result["status"] == http.HTTPStatus.GATEWAY_TIMEOUT: + if result["status"] == http.HTTPStatus.GATEWAY_TIMEOUT: raise RequestTimeoutError - elif "error" in data and result["status"] == http.HTTPStatus.BAD_GATEWAY: + elif result["status"] == http.HTTPStatus.BAD_GATEWAY: raise ServerConnectionError - elif "error" in data and result["status"] == http.HTTPStatus.FORBIDDEN: - raise AuthError(data["error"]) - elif "error" in data and result["status"] == http.HTTPStatus.BAD_REQUEST: - raise ReplyError(data["error"]) - elif "error" in data and result["status"] != http.HTTPStatus.NOT_FOUND: + elif result["status"] == http.HTTPStatus.FORBIDDEN: + raise AuthError("Forbidden") + elif result["status"] == http.HTTPStatus.BAD_REQUEST: + raise ReplyError("Bad request") + elif ( + str(result["status"]).startswith(("4", "5")) + and result["status"] != http.HTTPStatus.NOT_FOUND + ): # We exclude 404 since if we encounter a 404, it means that an # item is missing. In that case we return to the caller to # handle that with an appropriate message. However, if the error # is not a 404, then we raise. - raise BaseError(data["error"]) + raise BaseError("Unknown error") - return data, result["status"], result["headers"] + data = json.loads(result["body"]) + return JSONResponse(data=data, status=result["status"], headers=result["headers"]) def authenticate(self, totp: Optional[str] = None) -> bool: """ @@ -238,25 +217,23 @@ def authenticate(self, totp: Optional[str] = None) -> bool: path_query = "api/v1/token" body = json.dumps(user_data) - try: - token_data, status_code, headers = self._send_json_request( - method, path_query, body=body, timeout=self.default_request_timeout - ) - except json.decoder.JSONDecodeError: - raise BaseError("Error in parsing JSON") + response = self._send_json_request( + method, path_query, body=body, timeout=self.default_request_timeout + ) + assert isinstance(response, JSONResponse) - if "expiration" not in token_data: + if "expiration" not in response.data: raise AuthError("Authentication error") - token_expiration = parse_datetime(token_data["expiration"]) + token_expiration = parse_datetime(response.data["expiration"]) if token_expiration is None: raise BaseError("Error in parsing token expiration time") - self.token = token_data["token"] + self.token = response.data["token"] self.token_expiration = token_expiration - self.token_journalist_uuid = token_data["journalist_uuid"] - self.first_name = token_data["journalist_first_name"] - self.last_name = token_data["journalist_last_name"] + self.token_journalist_uuid = response.data["journalist_uuid"] + self.first_name = response.data["journalist_first_name"] + self.last_name = response.data["journalist_last_name"] self.update_auth_header() @@ -279,14 +256,15 @@ def get_sources(self) -> List[Source]: path_query = "api/v1/sources" method = "GET" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) - sources = data["sources"] + sources = response.data["sources"] result = [] # type: List[Source] for source in sources: @@ -305,17 +283,18 @@ def get_source(self, source: Source) -> Source: path_query = "api/v1/sources/{}".format(source.uuid) method = "GET" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) - if status_code == 404: + if response.status == 404: raise WrongUUIDError("Missing source {}".format(source.uuid)) - return Source(**data) + return Source(**response.data) def get_source_from_string(self, uuid: str) -> Source: """ @@ -339,17 +318,18 @@ def delete_source(self, source: Source) -> bool: path_query = "api/v1/sources/{}".format(source.uuid) method = "DELETE" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) - if status_code == 404: + if response.status == 404: raise WrongUUIDError("Missing source {}".format(source.uuid)) - if "message" in data and data["message"] == "Source and submissions deleted": + if response.data.get("message") == "Source and submissions deleted": return True # We should never reach here @@ -368,17 +348,18 @@ def delete_conversation(self, uuid: str) -> bool: path_query = "api/v1/sources/{}/conversation".format(uuid) method = "DELETE" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) - if status_code == 404: + if response.status == 404: raise WrongUUIDError("Missing source {}".format(uuid)) - if "message" in data and data["message"] == "Source data deleted": + if response.data.get("message") == "Source data deleted": return True return False @@ -405,16 +386,18 @@ def add_star(self, source: Source) -> bool: path_query = "api/v1/sources/{}/add_star".format(source.uuid) method = "POST" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) - if status_code == 404: + assert isinstance(response, JSONResponse) + + if response.status == 404: raise WrongUUIDError("Missing source {}".format(source.uuid)) - if "message" in data and data["message"] == "Star added": + if response.data.get("message") == "Star added": return True return False @@ -428,16 +411,18 @@ def remove_star(self, source: Source) -> bool: path_query = "api/v1/sources/{}/remove_star".format(source.uuid) method = "DELETE" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) - if status_code == 404: + assert isinstance(response, JSONResponse) + + if response.status == 404: raise WrongUUIDError("Missing source {}".format(source.uuid)) - if "message" in data and data["message"] == "Star removed": + if response.data.get("message") == "Star removed": return True return False @@ -452,18 +437,19 @@ def get_submissions(self, source: Source) -> List[Submission]: path_query = "api/v1/sources/{}/submissions".format(source.uuid) method = "GET" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) - if status_code == 404: + if response.status == 404: raise WrongUUIDError("Missing submission {}".format(source.uuid)) result = [] # type: List[Submission] - values = data["submissions"] + values = response.data["submissions"] for val in values: s = Submission(**val) @@ -484,17 +470,21 @@ def get_submission(self, submission: Submission) -> Submission: ) method = "GET" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) - if status_code == 404: - raise WrongUUIDError("Missing submission {}".format(submission.uuid)) + if response.status == 404: + raise WrongUUIDError("Missing submission {}".format(submission.uuid)) - return Submission(**data) + return Submission(**response.data) + else: + # XXX: is this the correct behavior + return submission def get_submission_from_string(self, uuid: str, source_uuid: str) -> Submission: """ @@ -517,15 +507,16 @@ def get_all_submissions(self) -> List[Submission]: path_query = "api/v1/submissions" method = "GET" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) result = [] # type: List[Submission] - values = data["submissions"] + values = response.data["submissions"] for val in values: s = Submission(**val) @@ -548,17 +539,18 @@ def delete_submission(self, submission: Submission) -> bool: ) method = "DELETE" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) - if status_code == 404: + if response.status == 404: raise WrongUUIDError("Missing submission {}".format(submission.uuid)) - if "message" in data and data["message"] == "Submission deleted": + if response.data.get("message") == "Submission deleted": return True # We should never reach here return False @@ -597,33 +589,24 @@ def download_submission( if os.path.exists(path) and not os.path.isdir(path): raise BaseError("Please provide a valid directory to save.") - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, + stream=True, headers=self.req_headers, timeout=timeout or self.default_download_timeout, ) - if status_code == 404: - raise WrongUUIDError("Missing submission {}".format(submission.uuid)) + if isinstance(response, JSONResponse): + if response.status == 404: + raise WrongUUIDError("Missing submission {}".format(submission.uuid)) + else: + raise BaseError(f"Unknown error, status code: {response.status}") - # Get the headers - headers = headers - - if not self.proxy: - # This is where we will save our downloaded file - filepath = os.path.join(path, submission.filename) - with open(filepath, "wb") as fobj: - for chunk in data.iter_content(chunk_size=1024): # Getting 1024 in each chunk - if chunk: - fobj.write(chunk) - - else: - filepath = os.path.join( - "/home/user/QubesIncoming/", self.proxy_vm_name, data["filename"] - ) + filepath = os.path.join(path, submission.filename) + Path(filepath).write_bytes(response.contents) - return headers["Etag"].strip('"'), filepath + return response.sha256sum.strip('"'), filepath def flag_source(self, source: Source) -> bool: """ @@ -635,19 +618,20 @@ def flag_source(self, source: Source) -> bool: path_query = "api/v1/sources/{}/flag".format(source.uuid) method = "POST" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) - if status_code == 404: + if response.status == 404: raise WrongUUIDError("Missing source {}".format(source.uuid)) return True - def get_current_user(self) -> Any: + def get_current_user(self) -> dict: """ Returns a dictionary of the current user data. @@ -662,14 +646,15 @@ def get_current_user(self) -> Any: path_query = "api/v1/user" method = "GET" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) - return data + return response.data def get_users(self) -> List[User]: """ @@ -681,14 +666,15 @@ def get_users(self) -> List[User]: path_query = "api/v1/users" method = "GET" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) - users = data["users"] + users = response.data["users"] result = [] # type: List[User] for user in users: @@ -713,16 +699,17 @@ def reply_source(self, source: Source, msg: str, reply_uuid: Optional[str] = Non if reply_uuid: reply["uuid"] = reply_uuid - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, body=json.dumps(reply), headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) - if "message" in data and data["message"] == "Your reply has been stored": - return Reply(uuid=data["uuid"], filename=data["filename"]) + if response.data.get("message") == "Your reply has been stored": + return Reply(uuid=response.data["uuid"], filename=response.data["filename"]) raise ReplyError("bad request") @@ -736,18 +723,19 @@ def get_replies_from_source(self, source: Source) -> List[Reply]: path_query = "api/v1/sources/{}/replies".format(source.uuid) method = "GET" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) - if status_code == 404: + if response.status == 404: raise WrongUUIDError("Missing source {}".format(source.uuid)) result = [] - for datum in data["replies"]: + for datum in response.data["replies"]: reply = Reply(**datum) result.append(reply) @@ -765,17 +753,18 @@ def get_reply_from_source(self, source: Source, reply_uuid: str) -> Reply: path_query = "api/v1/sources/{}/replies/{}".format(source.uuid, reply_uuid) method = "GET" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) - if status_code == 404: + if response.status == 404: raise WrongUUIDError("Missing source {}".format(source.uuid)) - reply = Reply(**data) + reply = Reply(**response.data) return reply @@ -788,15 +777,16 @@ def get_all_replies(self) -> List[Reply]: path_query = "api/v1/replies" method = "GET" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) result = [] - for datum in data["replies"]: + for datum in response.data["replies"]: reply = Reply(**datum) result.append(reply) @@ -821,35 +811,25 @@ def download_reply(self, reply: Reply, path: str = "") -> Tuple[str, str]: if os.path.exists(path) and not os.path.isdir(path): raise BaseError("Please provide a valid directory to save.") - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, + stream=True, headers=self.req_headers, timeout=self.default_request_timeout, ) - if status_code == 404: - raise WrongUUIDError("Missing reply {}".format(reply.uuid)) - - # Get the headers - headers = headers + if isinstance(response, JSONResponse): + if response.status == 404: + raise WrongUUIDError("Missing reply {}".format(reply.uuid)) + else: + raise BaseError(f"Unknown error, status code: {response.status}") - if not self.proxy: - # This is where we will save our downloaded file - filepath = os.path.join( - path, headers["Content-Disposition"].split("attachment; filename=")[1] - ) - with open(filepath, "wb") as fobj: - for chunk in data.iter_content(chunk_size=1024): # Getting 1024 in each chunk - if chunk: - fobj.write(chunk) - - else: - filepath = os.path.join( - "/home/user/QubesIncoming/", self.proxy_vm_name, data["filename"] - ) + # This is where we will save our downloaded file + filepath = os.path.join(path, response.filename.split("attachment; filename=")[1]) + Path(filepath).write_bytes(response.contents) - return headers["Etag"].strip('"'), filepath + return response.sha256sum.strip('"'), filepath def delete_reply(self, reply: Reply) -> bool: """ @@ -865,17 +845,18 @@ def delete_reply(self, reply: Reply) -> bool: method = "DELETE" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) - if status_code == 404: + if response.status == 404: raise WrongUUIDError("Missing reply {}".format(reply.uuid)) - if "message" in data and data["message"] == "Reply deleted": + if response.data.get("message") == "Reply deleted": return True # We should never reach here return False @@ -887,14 +868,15 @@ def logout(self) -> bool: path_query = "api/v1/logout" method = "POST" - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) - if "message" in data and data["message"] == "Your token has been revoked.": + if response.data.get("message") == "Your token has been revoked.": return True else: return False @@ -914,17 +896,19 @@ def seen(self, files: List[str], messages: List[str], replies: List[str]) -> str path_query = "api/v1/seen" body = json.dumps({"files": files, "messages": messages, "replies": replies}) - data, status_code, headers = self._send_json_request( + response = self._send_json_request( method, path_query, headers=self.req_headers, body=body, timeout=self.default_request_timeout, ) + assert isinstance(response, JSONResponse) - data_str = json.dumps(data) + data_str = json.dumps(response.data) - if status_code == 404: + if response.status == 404: raise WrongUUIDError("{}".format(data_str)) + # FIXME: why are we returning a string with a JSON-encoded blob??? return data_str diff --git a/client/tests/conftest.py b/client/tests/conftest.py index b6dbad4e6..e8af57ab3 100644 --- a/client/tests/conftest.py +++ b/client/tests/conftest.py @@ -4,9 +4,12 @@ import tempfile from configparser import ConfigParser from datetime import datetime +from unittest import mock from uuid import uuid4 +import pyotp import pytest +import vcr from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QMainWindow @@ -27,6 +30,7 @@ from securedrop_client.gui import conversation from securedrop_client.gui.main import Window from securedrop_client.logic import Controller +from tests.sdk.utils import VCRAPI, Cassette with open(os.path.join(os.path.dirname(__file__), "files", "test-key.gpg.pub.asc")) as f: PUB_KEY = f.read() @@ -35,11 +39,7 @@ HOSTNAME = "http://localhost:8081/" USERNAME = "journalist" PASSWORD = "correct horse battery staple profanity oil chewy" - -# Modify cassettes to use the following TOTP code. For developing new tests, -# you can modify this so you don't need to keep editing cassettes during -# development. -TOTP = "123456" +TOTP = pyotp.TOTP("JHCOGO7VCER3EJ4L") # Time (in milliseconds) to wait for these GUI elements to render. TIME_APP_START = 1000 @@ -290,7 +290,9 @@ def get_status() -> ExportStatus: @pytest.fixture(scope="function") -def functional_test_app_started_context(homedir, reply_status_codes, session, config, qtbot): +def functional_test_app_started_context( + vcr_api, homedir, reply_status_codes, session, config, qtbot +): """ Returns a tuple containing the gui window and controller of a configured client. This should be used to for tests that need to start from the login dialog before the main application window @@ -323,7 +325,7 @@ def functional_test_logged_in_context(functional_test_app_started_context, qtbot qtbot.keyClicks(gui.login_dialog.username_field, USERNAME) qtbot.wait(TIME_CLICK_ACTION) qtbot.keyClicks(gui.login_dialog.password_field, PASSWORD) - qtbot.keyClicks(gui.login_dialog.tfa_field, TOTP) + qtbot.keyClicks(gui.login_dialog.tfa_field, str(TOTP.now())) qtbot.mouseClick(gui.login_dialog.submit, Qt.LeftButton) qtbot.wait(TIME_CLICK_ACTION) @@ -468,3 +470,22 @@ def create_gpg_test_context(sdc_home): result.stdout, result.stderr ) ) + + +@pytest.fixture +def vcr_api(request): + module_group = request.module.__name__.split(".")[1] + library = vcr.VCR(cassette_library_dir=f"tests/{module_group}/data/") + context = library.use_cassette(f"{request.function.__name__}.yml") + # Override `Cassette` to use our subclass before we enter the + # context manager. + context.cls = Cassette + with context as cassette: + + def create(*args, **kwargs): + api = VCRAPI(*args, **kwargs) + api._cassette = cassette + return api + + with mock.patch("securedrop_client.sdk.API", new=create): + yield diff --git a/client/tests/functional/cassettes/test_delete_source.yaml b/client/tests/functional/cassettes/test_delete_source.yaml deleted file mode 100644 index 62a29389a..000000000 --- a/client/tests/functional/cassettes/test_delete_source.yaml +++ /dev/null @@ -1,2074 +0,0 @@ -interactions: -- request: - body: '{"username": "journalist", "passphrase": "correct horse battery staple - profanity oil chewy", "one_time_code": "123456"}' - headers: - Accept: - - '*/*' - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '119' - User-Agent: - - python-requests/2.26.0 - method: POST - uri: http://localhost:8081/api/v1/token - response: - body: - string: "{\n \"expiration\": \"2022-01-20T07:11:12.016192Z\", \n \"journalist_first_name\": - null, \n \"journalist_last_name\": null, \n \"journalist_uuid\": \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"token\": \"eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE\"\n}\n" - headers: - Content-Length: - - '317' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:12 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/users - response: - body: - string: "{\n \"users\": [\n {\n \"first_name\": null, \n \"last_name\": - null, \n \"username\": \"journalist\", \n \"uuid\": \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n - \ }, \n {\n \"first_name\": null, \n \"last_name\": null, \n - \ \"username\": \"dellsberg\", \n \"uuid\": \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n - \ }\n ]\n}\n" - headers: - Content-Length: - - '324' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:12 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources - response: - body: - string: "{\n \"sources\": [\n {\n \"add_star_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/add_star\", - \n \"interaction_count\": 6, \n \"is_flagged\": false, \n \"is_starred\": - false, \n \"journalist_designation\": \"consistent synonym\", \n \"key\": - {\n \"fingerprint\": \"04EAA26CE5C74286E78299ADA6122A68D47035C3\", - \n \"public\": \"-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\\nmQINBFGRfoABEADL8YaMOqcq70cdpry7h52gS+aPmIYnC2PStdwCojU0ntOI0B21\\nGQvOHmxgcwMvXfSqBBEYNIC3r3IRUouQgl3oOvf7+RK5GqDgnV3lcrm9wDKBE7he\\ncqBPfZ+5AcOcqubAYXUCSznMGoMIxbCtQWaOpiqGU2ruSpwlq4jukzdVXvo4Zb/L\\nHn89r7TJc4Udg3lz36gxp3Jm7aTdGX8VKafLFiuK2LT3lakgurUO87M8DIdULn04\\nMJaujBVxYmbCJnjLg/flhjRUA4PKw9Hdc9vYp/e0k/eueJsB+Xhixc7XCnh9eaZn\\nNOrMz+IHZ5AY77Gopq23cidWPWFj2b/+g9+k6/MUsg9S3tzYOJ+kU1vncZipnsnc\\nW+wJMlu2o6wU5nSPoNUf0JFN+rI/ZTsK3jjADMyIUIN0abXMZ/GeNoH4olsfJcSb\\nM/INzmXIoSAmEd6/gZ8d1dDJsPA9Wd1zBySWiHXzfpihEvSseCdZBYuBE9iSs/x0\\nG83FiOG1x5JtEl8Bc42m74KaeM8QjgujnpYODqYdnWI2VVH66GjOgYDbb72spEe2\\nXobdk8KtABq0yEav26ZmS0/Wqd4RD67mRbp0FRpblt5Bl4qb2fFy0jZeFQ8M0Msy\\nfF4YWDDgpkPSp0wINLrSWCDR9VkWTmIKW7F70aP/KjD1RN8421PesKKggwARAQAB\\ntHVTb3VyY2UgS2V5IDxDMjVZQkdOQVIzR05FNlRDWFBUM040VkVON01HRDNZUVA2\\nRVNHM1lIUkVEM1I2VzM3VEtMQkpKSjVIVEpZVkFNU1FDVlJRRE9KWEs2R1ZVRExD\\nSDIyNkdMSFU1TjZWS08zNUFDSzdZPT6JAk4EEwEKADgWIQQE6qJs5cdChueCma2m\\nEipo1HA1wwUCUZF+gAIbLwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRCmEipo\\n1HA1w7iLEAClnTccq87JEHCp9mJ0mT7BHPGakRNzzvyZj8xgW+jaIdFH3lF+x3vE\\nWoJzvUP3js+Cne/hd/+I1fWBMcEERajWPUSXC+pqEBsOdAWrJ4xi0zI32ofEuFGc\\noTVoXLhJnrzDZM1TqK58nwZZxjwL1XzuLtvkAz+utkbI7rnNXRQMzoR3LazUjz9+\\nArPFjaiDjxAsF90VELvBjKmC1tYSNrr/XEwl6yTXBagf2VchVLUE+Y/0ozTFv+Cz\\nLeiQh+EqE8xhKkuELLkNUjx6Z2oVK91MVrCTLvnxsNGyoSLyH7CWZeFodCQYF3k7\\nF/zGe9/KE6/n6uZ8EdjI50Rd/h99cYDbHt8ljDeqhu59V2xqzb+sTWpl7WliiVx3\\nbrboXxIFWuidXYJFlaXy3X342dTwqVDVE3rW+T0r77ZMO3MPMRrtbyjSL5+yqWuw\\nS/BLuhorFgNdxP/uMKIz89xAp2diQ+6USAOoEIaWkOk+f45s2bXyjS0EzmeowYRG\\n6IwgqLqopx2w8Mx8o2/3NkC0RfehkF0ideMHZpTXW2WAjApJcnXDDxDfwhr/xSwh\\nzS0dgD4dsdpRWoocv3zXnSv5L9JetZGYM0/CnxG8SjZ48zStjpsenKz8X0vDJAai\\nSlXnUn6TGzHZxuPyNegZ4hwLW4YlMkktJAZRLWZNW8BYQZGc03Z2DQ==\\n=lJ7v\\n-----END - PGP PUBLIC KEY BLOCK-----\\n\", \n \"type\": \"PGP\"\n }, \n \"last_updated\": - \"2022-01-19T23:08:49.528506Z\", \n \"number_of_documents\": 2, \n \"number_of_messages\": - 2, \n \"remove_star_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/remove_star\", - \n \"replies_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/replies\", - \n \"submissions_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/submissions\", - \n \"url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa\", - \n \"uuid\": \"56d6777c-fdb6-474c-9d3b-0b7b43beabfa\"\n }, \n {\n - \ \"add_star_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/add_star\", - \n \"interaction_count\": 6, \n \"is_flagged\": false, \n \"is_starred\": - false, \n \"journalist_designation\": \"concrete limerick\", \n \"key\": - {\n \"fingerprint\": \"CA8A176B4D5D3666ED88B03BC5E9954B1492AE1F\", - \n \"public\": \"-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\\nmQINBFGRfoABEACtbh8mDuBbRxk7YGntX40e41q3r6mLgGmV5p26GZi3b/fAPoWA\\nJjo/Np5uBI+Ye/MZNZBl22aGIh3iamNXpywjrro1xCFryAhdFMj4eKuarekVbsNV\\nj0K5AWH2gomzJ27f+9+rkn+R5gtvRqeMA0tVu7pQQ7gw/n/1XIJ4X0M7oRHPWNAX\\nOvAJe/60jKTAiwNdgwE2a5aOTXrtXz20Je7bBq6TtKAWa9tdB+W2JUNH5IEmnhYA\\ntWw3/GliQHphPizpa4eE1jgF3IJtNf7hPTeJ7S50XXpolfmIaLYohWDuVi4LFVGC\\n2GGzasNefQJIoQXkK2UmYhhck0T4U5zwfl5RkuftOjGvHDa4U7bSRz3rl3MCzmGc\\nlvA028aMRrYg4nBu0ryVlVjAV93n8FTKasURjsyLVBfb+Fzxu1ebbG8rakvHbAbk\\nK25ZP+mNyu2QZ0WsM6j3C7afvAJDR0Mkj0KWBjc5JHMUtqupPwpK/8eswlecx7Yx\\ngLAwqkmYvFUiKjKAbUYbaOe4YJEUj4h/nxayXE2XhptLlL8m4oopflANRsqc00+F\\npQqcznyL0a89JKBmBaT8xPPK+GOtrs0EU9mz2IhAB4HxEKuVFuwOg7AIFLO6gRN/\\nLbqJvLz1IO3yM10O7gCb8ErPxrnByBkP417YWddnx9pPw0vPgPXy2lbo6QARAQAB\\ntHVTb3VyY2UgS2V5IDxPM1hKVUg2TkNaWEEzSlpOUlpSRlM2RlRaQURTUzNNVk5F\\nVFlNU0lRWjVZSDNUTDc2WFk3VjNQRTZSSkVINDRKMjZXM1pZMlVJNU9KMk00V0VG\\nWE1aRVdJWlBHS0NKN0VLTVRCQjJBPT6JAk4EEwEKADgWIQTKihdrTV02Zu2IsDvF\\n6ZVLFJKuHwUCUZF+gAIbLwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRDF6ZVL\\nFJKuH04ID/9Xl2jbyBsu+JHS3fsMDSZE0L39HhqbRKqrUxq5U9vb3aWU3Imf3Tu3\\nez8Sp/aThXOJKuC9QeJ2gCIe9+V+OGVYvUl67P3xxKzIUmlLlk5cbosC9m/J4MMZ\\ndmSok8XBgOWYWuNbcCNiW0msfDijJH1diH6tDc9UEzcTvTbWHqbl3S27uwVced3O\\n8OAY0MGcB6Tw1yRBbv7fJ4nWKeu3kmzrepRQYh9cEMEf+pDE0RUkoORiQI5vmtzL\\nv454PfNGGuGijMQm64tYqe33fwMR0marbLyYXTSMlzEDF5AxeaKjDVI4kEe6eUT4\\n8kLsvRl2nPX1gbrBSkHSZ21/oMkhdlGhPyb4xKcqCVkzpQJpCsATmAkjtp/IHJib\\n2mu6TzhAIvANP5jqiGE128lZpPBILq3PIrhXqVDyLWpl6xTSHz7rhxVXtDHJZoIz\\n4QJM7Dl9V0s/UQ5hJdmx5L0aEP+7b46+3kvgbPvItaRiF11L7fRQwXMNoI8bm47T\\nbfW5nJK8p6O5VssHtFYqL9rKYBDdk6JYsiZ8xvTrqTRMK1xJEsuF3Tuv73JmMQtF\\n7wQq8rZg0cbINpJuOBRsvEAo6ATJBq+HOCAuqvhJ3Kx9lixLnURP4dybKJoTdWJP\\nSDgLwly7bulTF+fHQSlD9cypaLiw4cyzFubhw4OWEJYMAsYcbfBqYA==\\n=i+xf\\n-----END - PGP PUBLIC KEY BLOCK-----\\n\", \n \"type\": \"PGP\"\n }, \n \"last_updated\": - \"2022-01-19T23:08:51.571224Z\", \n \"number_of_documents\": 2, \n \"number_of_messages\": - 2, \n \"remove_star_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/remove_star\", - \n \"replies_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/replies\", - \n \"submissions_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions\", - \n \"url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"uuid\": \"ae59153b-0871-411a-a72a-0f4c41a76ee0\"\n }, \n {\n - \ \"add_star_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/add_star\", - \n \"interaction_count\": 6, \n \"is_flagged\": false, \n \"is_starred\": - false, \n \"journalist_designation\": \"indecorous creamery\", \n \"key\": - {\n \"fingerprint\": \"04DD6C14755616B9F944F87311961223C70DEA58\", - \n \"public\": \"-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\\nmQINBFGRfoABEADEMD/A2IVlAmhB3Vu3jDlG3UFli/e20GXvfeW6S0PFEuvE9Po9\\nCjI43sFdMVvRUvtaIP5PE1zU4OuN1gi6jpKp5puulnddV6jP0GXqK+hqVXjiaf58\\nhUkuvpK2CaHf/5DvGdSW2IZLB9oP/UtWYTBUm7dER2Fc+rMY13fUMEsGKyJZ9wB3\\ny4CrJpMw7TNTefVx6vrlbCVEB4nksod+A7wteLILbeGj26D1A94vH1V4iLdOObW3\\npbTX4Yra1CpxclEsHyaS7tZ+4bQOmh0OdVG7ZW4MZPYp+1BIqt+e48042Rq1jIHu\\nHVApvHynPDt2tD/KiymDM3Bt69Dy9rHrWEFlWAS+Fpgo7qBQ9QF2fHWzpHQyhcTB\\nM3zQ2LraeOrBWgzjgCRIei+sga6w9Tjk8fMZKLl7HPkjRZxOFU4GJLjkxf3Lw1Av\\nCo3kQijDzj0nN/qyebcD2/v6vz5/5D8iS85fJdgLwds7ajXXgk9/M11Bkze1RT+2\\nYCmsUW999wF+AZmeR6ZFdUfcOpJE/99zs6GIRIo+ikPWiMcs4/7jAlrierrAtuhH\\nl6luFRIz6utBFWIleZosxnx3ZqRAv1DUdig3BnIliD3Y53y0cHbFFLOX428ZGKCp\\nJ9Of22l5XfMlT6B8NCJgRcQc77beedl+1XcQP64X+FgddottileDhsiRNQARAQAB\\ntHVTb3VyY2UgS2V5IDxHSlFBVTRBVUlOQVNBRk81R1I3N0NMNUpDWFRMV0FXWjJU\\nV1BKSExDSTRJWFpNRVFKWVlIRFVUWUFNWjJOVDJLUDdPN09GSlRRSkdTSFJJT1dP\\nM05aS0VGRU01QklHTkNWVkFFT0xRPT6JAk4EEwEKADgWIQQE3WwUdVYWuflE+HMR\\nlhIjxw3qWAUCUZF+gAIbLwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRARlhIj\\nxw3qWEDyEACKKS0y7ApY7CMGuuU6BltrUyc7A5UcCe6vnCREX4662qkHgaDLmIpa\\nb5t+hvtOicEwegoFsBAnjnG+Vs+AU1DDzXREojZ0T39Hyq0PYS7HbDWJRUSfl//Z\\na566rtbdzv1GEc7hMAEi9pKplR3uEQlQAp1G6W1Yzf5WuwmdWMOactzbENJTnbc1\\nSBe/oKbH56UEMX7KLr5MODQ6IM+VCqRI/k6Px065q8scAeEQERwUFdy33BBzk+g7\\n/uYPC74NnfISP6Tj94oFEySs1HC2hIaZlUQor3ZJOzvZ3Vm8hix7JdjBVdqdHFmx\\n5+Ft211Va6v1dKCUW73GPvYkv0bt4CeAV9fhyQOSMSENTiNVVh8L2+dCXVQXhFUw\\n3Hmu/tOj+r2B8+vWWHuhbFjgeAiXFkHFDT1a3xZ98n5g5SNwoiBJDuyWjPgr0vG3\\n/+1wgTovRVbt62H1VgRsP49wMS9EBz1DV1q60GcWD40FNfkJx7W1T0RtUgpKp3hH\\nw06RJFAzeMJtXz89mFpIQfkVwBflne5HDQywIT8o0TnxAh06Q4ROqhFydDSB0HTv\\n6NJVRhiSiwGmYiZi4DVwv7exttrfv6h1TX99MjR1e3kjki/IjeI/pW42GgFUZVN5\\nWRzx2yiSIfz1rhBqnRAtZWConlmG2X3LRbUFtz1LHsbC8UqKdtlB1g==\\n=oWMO\\n-----END - PGP PUBLIC KEY BLOCK-----\\n\", \n \"type\": \"PGP\"\n }, \n \"last_updated\": - \"2022-01-19T23:08:57.846667Z\", \n \"number_of_documents\": 2, \n \"number_of_messages\": - 2, \n \"remove_star_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/remove_star\", - \n \"replies_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/replies\", - \n \"submissions_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions\", - \n \"url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"uuid\": \"55fb95c1-cff3-430a-8c05-125c67c81a6a\"\n }, \n {\n - \ \"add_star_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/add_star\", - \n \"interaction_count\": 6, \n \"is_flagged\": false, \n \"is_starred\": - false, \n \"journalist_designation\": \"conjunctive lavage\", \n \"key\": - {\n \"fingerprint\": \"F71969D1705E2E3E374B95992DA6D8DCEE36946B\", - \n \"public\": \"-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\\nmQINBFGRfoABEADcaB1fww19PLIREowYKfNZiVoWpLYxRnw1U/Iz4JbnEJ7TuIlm\\n2Q46Hr9kR7zQVb5okjn40whN0JA3lJcfPZdjfxiCt8VYI7vacUxVZgXWJCR83vO4\\nNSD1YnZD5KXi0B6PGKIhry1Hqc+hzmMAFYGGdi4h5EKxinNmKTO+E3Zupeydm0KK\\nCBwXroROAs/5+s63oj5+nuqlPCTcEL3SGjH8zXIw+TN0mBhQhGlyqofIW/JEaviP\\n+frUL6WPa3AoUBE+TAF1rmXr30phZU271zfAYhe0B81gtrUTSg49uUYQuCf1xu92\\ngbuOmcYTQvdzgGDp8cNWL5cmQCdvoGTGH5PYodqMGcRfWqB1dl37RCsqDcCzssdv\\nJiUe8qC88n0tQl/gJOgniEhKEok5EiaGuuLz9j7waGB1aBgHLPsibDGQVyYn9ZYD\\na3E9cL0BHzsWJc9i1hFE2cmTXzmJ7rTXyvHSvidT6s2cljuih1Q6e5qNOcJPAuv9\\nY2xuZHn+rTaJSLM30X7PngrAP2jfepraz7zy2lE4Uex9dLQNPMcYhjPc9SwKjk8g\\njDkhCGW6daRCpzNUR/ydYGlfN00L6MPo0S3XG/x88f+OwqgfSpgrfSijqDTLxbo1\\nO4rTW+KSiVy2P9DfuLhZv+HcNiinY0EP3qbuuXKk7VSMeCir+HgeDce+pwARAQAB\\ntHVTb3VyY2UgS2V5IDxTV1pWS0hOTlBLQkIzVTJDRjNBMjRIUkJZRlRNNkNDU1U3\\nM05XQlhNTkw2NVFRWktEM1gzRllNTFVDVlBKRlhCRUJWRVkyQklKWVJLUUQ2NUFT\\nS1IzQTNaTVhaMkFOTkI2Sk1CVEJJPT6JAk4EEwEKADgWIQT3GWnRcF4uPjdLlZkt\\nptjc7jaUawUCUZF+gAIbLwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRAtptjc\\n7jaUawViD/9O2J9EsxOmaSB3XI9q0EyLvOZPh+r9TeOGA4kqQlOH3PeMP1lxQ7v1\\n3LR7OCjM2pBNHww7rRkYNoJX4dA/UjZ1UcerIAbxa2Z4v7X69akKItw889UCW6Go\\ncUtco2XqkjaThsV/io19+6qFicrWAumpFtH2Dt8iVsHzOYWpijPK70AxJqODg+nK\\nv4k/+zqAePbLOCCCuvnhBduJCEd3dA0G7ow0H/AzgpPKOEswbYK6JJYX8Gsq9F3n\\ne+PkBJ3Op4/qUELYQYEBbF2qy+XPfhOZsJ4v/HDb+eutZNmATtpGZGNJznyLFoZX\\nbNI/U2XIlQYBDeYTOVbNPPVwoVucoXG1iGsp+2ZFvLgP4XGRxdH9oyiia9FC+id1\\nwCtS6dRWRKv1VJwVetGBncAdwmugCkQoJ/gGwcTkJLhOVyoZZruTR8aLOE+ArTUg\\nfgKBVpeT9he8ELDZFrPtAnDTpMS+RrVsF8Y1sih7O8VCxsxGRegKlQcxgPp7/MdG\\nwFOlulTqCSu+fZfkid4rvnRGcPRp1DQohwXiK/UpDIRYTPERHQTEm2fK29FzmruI\\nr4zotTaeHhztY5jrqZqzkMy6/teHE5CGq5mKQsXzQFjb5hKEYg4TwAazPRtH3WOo\\nkZ5ISlxKvOdf8jA9hWKFrREtk9t9blD0IA3ffzfO5aad+aZjnqsgyw==\\n=ccYc\\n-----END - PGP PUBLIC KEY BLOCK-----\\n\", \n \"type\": \"PGP\"\n }, \n \"last_updated\": - \"2022-01-19T23:09:00.294006Z\", \n \"number_of_documents\": 2, \n \"number_of_messages\": - 2, \n \"remove_star_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/remove_star\", - \n \"replies_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/replies\", - \n \"submissions_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions\", - \n \"url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"uuid\": \"50c5fa95-eb69-49b6-8599-62b12cff7d7d\"\n }, \n {\n - \ \"add_star_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/add_star\", - \n \"interaction_count\": 7, \n \"is_flagged\": false, \n \"is_starred\": - false, \n \"journalist_designation\": \"sixty-nine alliance\", \n \"key\": - {\n \"fingerprint\": \"7034A99B359CA2DD3F57E251437B6C3C6984302F\", - \n \"public\": \"-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\\nmQINBFGRfoABEAC8d/LgDtvyeg/SNsUcUPRY7JZGFbE3peoduYiqd29LW/BXoInn\\ntRV3Ks5H8QLH3/qS/zWwiE4x2yE8cOykWj/lPMlFCDYdWK4f55eS1LcxN+WtLiaL\\ndDQG84KICZznbqTxlvdizLwCvch9Y19dPszPuwrBJ2KbOsngPfHDARs2aU++J1d1\\n7MjIpBLJHTlYKRdutANtxEKCq+KX9/K8GnjZYLhmmecaVr6OoSp3Nq6zlvJe7qPb\\nc1IUJhA1oDyNVBAPs5ROKkM6qhDJmI9OpKoGVGWG7u3kDQ3Oo59wBoC65xTZNFy1\\nGKcQbCcegKsnxdchBO9nMK3wh8H6JUkpdXPrurysHqQ6JIAar0rXIlOvg8kD6yNU\\n7bYK6xetBzkYBGgz7vbgYq+k2ur3nQLvJmBnPVqY/7bjSGDIfbkJWOudD2LaqQUc\\nIUeBpTlOsqfVhXwfen+ynntPdSQU14ILmQAztFzZor2leNWAR6pYG6ZI3vEzAX3l\\nWPzmS7L13VC1w11IG0wdKuzhx1jHGJ32JrNyL4LoJ1O++8GWlJS0+ZC85gwIaFQC\\nLB+sGw4PruxLUGFe2ZLYWgYnN3Iw5JBPxfc+Kxrp1xhHCZNdC1B1ajtkOwvdZbIU\\nOP9Cp5MRt5AeGBZ9ujIMsAxOZrPeN574ewqnY+z431eC6rNFzdmlY1Av8wARAQAB\\ntHVTb3VyY2UgS2V5IDwzSjI1UlA3NlZUWUwzVktMV1haTENOUFI1WUZMQzJQMk9Q\\nRFRETE9IVVFQQkkzN0RZWE1CWkpORFRVSkxSWjNDUlc1RkdXVEJNSDY0UTNBN1BZ\\nTk9KTjY0T09YSFpRRE5STDNRWEVJPT6JAk4EEwEKADgWIQRwNKmbNZyi3T9X4lFD\\ne2w8aYQwLwUCUZF+gAIbLwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRBDe2w8\\naYQwL7osD/9nj9I/89AR2p+MDw+RqGjNrEMnIyCC1+IneGC5MJXLYb/9oz9JRMrb\\n/+Gk+MhPjkgHVbI9BzByIzNh0stYF1T17rJDIyehjfbejYQKFwJd1+QHCfSgLIQQ\\nNOtKKr9iX5fUdPzlLzkdaTRGMidUTqWuY77wgmZoKN1a1Q801NXjIkY3QJ5GpjSf\\ncdvgu77k7y/0juUu0eTeNpd1TXs/GBitETnfDEKcVUkk8x+OwvSFE7VrWJCNAH/x\\nOAQUeT9S7CczoUeFWCII880xFcpdynt+ogYyxVh22RV13HJ/HJlmUA+9cpQ6ntAW\\nXdhKS814mJjqfTk5j2ZzLwKekqQgUSjCB7ucbEPhaHdQHShfuNQg9EhtP2Qy+Ptg\\ntGFMF4f+s9anFobioeYnS9S3JuR73UHD6XOz4GDgGx/3kdlxwRfjOqnRWzC3oNmU\\nVmT2caEmXnjEqL3FP1wVOEcciBqOAgT0QsMB06eOHL+cJxMOE6j/Wo4Y2loF0+Bq\\nR0KMqbg0lpSyLHjTmOo15DgzohSALI44niM1SaVGGlzOawb5zOd8ownvfwcut1wG\\n0UxhwbyoiHblTySzzjhekJQGMGQOyRUIfbjbNtHKeVFVEosM5dUhXWRA+8n1uhc+\\npqdAhXSd9yEIjy8dIc7USlTTqEEOYYXetEWYJP6tolKuggSiiUB49A==\\n=9Hjj\\n-----END - PGP PUBLIC KEY BLOCK-----\\n\", \n \"type\": \"PGP\"\n }, \n \"last_updated\": - \"2022-01-19T23:09:01.659060Z\", \n \"number_of_documents\": 2, \n \"number_of_messages\": - 2, \n \"remove_star_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/remove_star\", - \n \"replies_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies\", - \n \"submissions_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions\", - \n \"url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"uuid\": \"92b1914a-1b1c-4674-baad-1fb662aed682\"\n }\n ]\n}\n" - headers: - Content-Length: - - '13467' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:12 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/submissions - response: - body: - string: "{\n \"submissions\": [\n {\n \"download_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/submissions/7e2de803-ccc1-42d0-87f3-76972745d11c/download\", - \n \"filename\": \"1-consistent_synonym-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 623, \n \"source_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa\", - \n \"submission_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/submissions/7e2de803-ccc1-42d0-87f3-76972745d11c\", - \n \"uuid\": \"7e2de803-ccc1-42d0-87f3-76972745d11c\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/submissions/7064722a-8970-4fc0-b8df-8b8c05a95d81/download\", - \n \"filename\": \"2-consistent_synonym-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 692, \n \"source_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa\", - \n \"submission_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/submissions/7064722a-8970-4fc0-b8df-8b8c05a95d81\", - \n \"uuid\": \"7064722a-8970-4fc0-b8df-8b8c05a95d81\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/submissions/d2aa85bc-28b7-40e4-bbc2-fb7fa588965b/download\", - \n \"filename\": \"3-consistent_synonym-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa\", - \n \"submission_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/submissions/d2aa85bc-28b7-40e4-bbc2-fb7fa588965b\", - \n \"uuid\": \"d2aa85bc-28b7-40e4-bbc2-fb7fa588965b\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/submissions/42f45442-ee20-4745-8518-c8a01bad5f46/download\", - \n \"filename\": \"4-consistent_synonym-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa\", - \n \"submission_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/submissions/42f45442-ee20-4745-8518-c8a01bad5f46\", - \n \"uuid\": \"42f45442-ee20-4745-8518-c8a01bad5f46\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/48bcb4a3-6f23-479e-a718-e0b93fd4b9c1/download\", - \n \"filename\": \"1-concrete_limerick-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 611, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"submission_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/48bcb4a3-6f23-479e-a718-e0b93fd4b9c1\", - \n \"uuid\": \"48bcb4a3-6f23-479e-a718-e0b93fd4b9c1\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/d8db9ba7-4789-41c8-9f7b-3761a367816c/download\", - \n \"filename\": \"2-concrete_limerick-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 757, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"submission_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/d8db9ba7-4789-41c8-9f7b-3761a367816c\", - \n \"uuid\": \"d8db9ba7-4789-41c8-9f7b-3761a367816c\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/648932a9-7e82-4fde-a65a-fee812b50ec0/download\", - \n \"filename\": \"3-concrete_limerick-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"submission_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/648932a9-7e82-4fde-a65a-fee812b50ec0\", - \n \"uuid\": \"648932a9-7e82-4fde-a65a-fee812b50ec0\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/e0565187-d9ea-494b-8ea0-173befacb1f3/download\", - \n \"filename\": \"4-concrete_limerick-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"submission_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/e0565187-d9ea-494b-8ea0-173befacb1f3\", - \n \"uuid\": \"e0565187-d9ea-494b-8ea0-173befacb1f3\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/ecc07e49-be88-40d5-8e99-bfb3b3812668/download\", - \n \"filename\": \"1-indecorous_creamery-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 593, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"submission_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/ecc07e49-be88-40d5-8e99-bfb3b3812668\", - \n \"uuid\": \"ecc07e49-be88-40d5-8e99-bfb3b3812668\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/c60627e5-dfc6-42dc-8874-b290ef09a2d9/download\", - \n \"filename\": \"2-indecorous_creamery-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [], \n \"size\": 595, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"submission_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/c60627e5-dfc6-42dc-8874-b290ef09a2d9\", - \n \"uuid\": \"c60627e5-dfc6-42dc-8874-b290ef09a2d9\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/0e734035-3193-4c94-a86a-41d04332d8c0/download\", - \n \"filename\": \"3-indecorous_creamery-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"submission_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/0e734035-3193-4c94-a86a-41d04332d8c0\", - \n \"uuid\": \"0e734035-3193-4c94-a86a-41d04332d8c0\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/93d72061-a8f5-4166-9a7a-3beeea4989e2/download\", - \n \"filename\": \"4-indecorous_creamery-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"submission_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/93d72061-a8f5-4166-9a7a-3beeea4989e2\", - \n \"uuid\": \"93d72061-a8f5-4166-9a7a-3beeea4989e2\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/f2fc98d1-8acb-405f-a4c3-c93bf23febba/download\", - \n \"filename\": \"1-conjunctive_lavage-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 638, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"submission_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/f2fc98d1-8acb-405f-a4c3-c93bf23febba\", - \n \"uuid\": \"f2fc98d1-8acb-405f-a4c3-c93bf23febba\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/4abcd4b4-3922-4ae0-ad97-9186f51e172c/download\", - \n \"filename\": \"2-conjunctive_lavage-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 667, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"submission_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/4abcd4b4-3922-4ae0-ad97-9186f51e172c\", - \n \"uuid\": \"4abcd4b4-3922-4ae0-ad97-9186f51e172c\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/2281fccc-4cae-4228-a837-e6f3a3e1e6d2/download\", - \n \"filename\": \"3-conjunctive_lavage-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n - \ ], \n \"size\": 661, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"submission_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/2281fccc-4cae-4228-a837-e6f3a3e1e6d2\", - \n \"uuid\": \"2281fccc-4cae-4228-a837-e6f3a3e1e6d2\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/098a7d90-0ae4-47cf-a7a2-2afc00094a3b/download\", - \n \"filename\": \"4-conjunctive_lavage-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"submission_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/098a7d90-0ae4-47cf-a7a2-2afc00094a3b\", - \n \"uuid\": \"098a7d90-0ae4-47cf-a7a2-2afc00094a3b\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/546e7e6b-ac50-4ba7-b738-82f0d261feee/download\", - \n \"filename\": \"1-sixty-nine_alliance-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 591, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"submission_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/546e7e6b-ac50-4ba7-b738-82f0d261feee\", - \n \"uuid\": \"546e7e6b-ac50-4ba7-b738-82f0d261feee\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/987ef070-4e9e-43e0-98e0-2c623607aae1/download\", - \n \"filename\": \"2-sixty-nine_alliance-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 591, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"submission_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/987ef070-4e9e-43e0-98e0-2c623607aae1\", - \n \"uuid\": \"987ef070-4e9e-43e0-98e0-2c623607aae1\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/2df5a904-e89a-48f9-9e33-5b9759317f1b/download\", - \n \"filename\": \"3-sixty-nine_alliance-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"submission_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/2df5a904-e89a-48f9-9e33-5b9759317f1b\", - \n \"uuid\": \"2df5a904-e89a-48f9-9e33-5b9759317f1b\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/03d1920d-d4d8-4580-9c42-6333c812383a/download\", - \n \"filename\": \"4-sixty-nine_alliance-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"submission_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/03d1920d-d4d8-4580-9c42-6333c812383a\", - \n \"uuid\": \"03d1920d-d4d8-4580-9c42-6333c812383a\"\n }\n ]\n}\n" - headers: - Content-Length: - - '12734' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:12 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/replies - response: - body: - string: "{\n \"replies\": [\n {\n \"filename\": \"5-consistent_synonym-reply.gpg\", - \n \"is_deleted_by_source\": false, \n \"journalist_first_name\": - null, \n \"journalist_last_name\": null, \n \"journalist_username\": - \"dellsberg\", \n \"journalist_uuid\": \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", - \n \"reply_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/replies/9df9083e-1ac1-4085-883d-8c9982b6ad79\", - \n \"seen_by\": [\n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n - \ ], \n \"size\": 1150, \n \"source_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa\", - \n \"uuid\": \"9df9083e-1ac1-4085-883d-8c9982b6ad79\"\n }, \n {\n - \ \"filename\": \"6-consistent_synonym-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"dellsberg\", \n \"journalist_uuid\": - \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"reply_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/replies/ba38afd6-aadf-48d1-a599-bd74601105d9\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 1219, \n \"source_url\": \"/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa\", - \n \"uuid\": \"ba38afd6-aadf-48d1-a599-bd74601105d9\"\n }, \n {\n - \ \"filename\": \"5-concrete_limerick-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"dellsberg\", \n \"journalist_uuid\": - \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"reply_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/replies/9bb8030a-8561-4a03-85dc-e921bd6a891c\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 1138, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"uuid\": \"9bb8030a-8561-4a03-85dc-e921bd6a891c\"\n }, \n {\n - \ \"filename\": \"6-concrete_limerick-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": \"\", \n \"journalist_last_name\": - \"\", \n \"journalist_username\": \"deleted\", \n \"journalist_uuid\": - \"deleted\", \n \"reply_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/replies/0a82f046-581c-49ef-9b51-ce5b73e45c1a\", - \n \"seen_by\": [], \n \"size\": 1284, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"uuid\": \"0a82f046-581c-49ef-9b51-ce5b73e45c1a\"\n }, \n {\n - \ \"filename\": \"5-indecorous_creamery-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": \"\", \n \"journalist_last_name\": - \"\", \n \"journalist_username\": \"deleted\", \n \"journalist_uuid\": - \"deleted\", \n \"reply_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/replies/1c2ff7fa-252a-426a-83e9-5840cf657739\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n - \ ], \n \"size\": 1120, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"uuid\": \"1c2ff7fa-252a-426a-83e9-5840cf657739\"\n }, \n {\n - \ \"filename\": \"6-indecorous_creamery-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"dellsberg\", \n \"journalist_uuid\": - \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"reply_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/replies/5f5707b7-ee1d-410f-94be-1ba8c1929264\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 1122, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"uuid\": \"5f5707b7-ee1d-410f-94be-1ba8c1929264\"\n }, \n {\n - \ \"filename\": \"5-conjunctive_lavage-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"dellsberg\", \n \"journalist_uuid\": - \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"reply_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/replies/158dfd73-3cb3-4a6e-85b3-f37ae54e0802\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 1165, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"uuid\": \"158dfd73-3cb3-4a6e-85b3-f37ae54e0802\"\n }, \n {\n - \ \"filename\": \"6-conjunctive_lavage-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": \"\", \n \"journalist_last_name\": - \"\", \n \"journalist_username\": \"deleted\", \n \"journalist_uuid\": - \"deleted\", \n \"reply_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/replies/24fbb6b4-504c-4fa7-9971-e6f2d1447a48\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n - \ ], \n \"size\": 1194, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"uuid\": \"24fbb6b4-504c-4fa7-9971-e6f2d1447a48\"\n }, \n {\n - \ \"filename\": \"5-sixty-nine_alliance-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"dellsberg\", \n \"journalist_uuid\": - \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"reply_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies/4dad63f1-dc12-4162-9c59-065c88b2a8b4\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 1118, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"uuid\": \"4dad63f1-dc12-4162-9c59-065c88b2a8b4\"\n }, \n {\n - \ \"filename\": \"6-sixty-nine_alliance-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"dellsberg\", \n \"journalist_uuid\": - \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"reply_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies/d5b658be-aabd-4d7b-89c1-51de7fa246a0\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 1118, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"uuid\": \"d5b658be-aabd-4d7b-89c1-51de7fa246a0\"\n }, \n {\n - \ \"filename\": \"7-sixty-nine_alliance-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"journalist\", \n \"journalist_uuid\": - \"a9f8835b-52a6-4845-b428-61cc10561a0b\", \n \"reply_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies/f774fd7f-55ad-45a6-9a92-05053f9628bf\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n - \ ], \n \"size\": 1605, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"uuid\": \"f774fd7f-55ad-45a6-9a92-05053f9628bf\"\n }\n ]\n}\n" - headers: - Content-Length: - - '7167' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:12 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/546e7e6b-ac50-4ba7-b738-82f0d261feee/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqARAAmwUjOf3oGUcC5K7tSj2wxiaUdEVeNF4vF3dX1fehU6KBpQhv1Fq1RkRg - 1xM0d/QOpfw31CX3ZS2hPdA0YkFt8xCNHi2UYY2Klumo9clEx5TsyF2xQ0YKSZ5zNlqVJWKRpa1t - bhtG3nRC7KQfEsQNQyLgQM/l9EJtzrYoYJEgd6vj9m8kPYsPhNnX4xtV9I4CFam1fwKqdJvjRiHd - 2v48TXcqxYywEwUKyrPyeLUvhFaPfYX3d7QVKd94Wj9FUcccV3Sn1JNeggVKuyo2i4k4ISkGGRr5 - Dr+Z7WVOTzZ2A/Ec7X5onGDbi1XGlrK94PaOEe00ER8sSqGQKDmfTu/RgHp2vwi5hvBUtOy7171f - 5lf16EIXP9WzNq5svfBBcRSiqTAXIIZ7L1gT1XT78edb/1UTAzj8MWv7AjOCWX893AzSS0QT52qb - vtdFygfDSLjTlOLS5S5mSwXySnTMEWgxtr7MEMOiNOiYmL/DGlHHMBv+k0KwcCj7UAQ6Sxs5Ek2V - nUP12NtHqUv50LWhIx1sec4SlinNwRyUXlBz03ZKazij654snOziaTHIS5ColH1Dybymz04FjWsZ - 1g7J09SSwH2SFCX/ZC/F1+DrJf6aXvjBtS6K1jB0179vzLqtOc+g+IT4R7RGZoc5SJNcIwNzSAhR - Psvoid62jXUBMluHUGnSPgFsdF4s8vKoV+3hb12cuGou87Qthv62oGM2k5aX2KHk/AWAcQw4LeT+ - iYWJWWBwFLOt2WUfZcX+rKQUquZi - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=1-sixty-nine_alliance-msg.gpg - Content-Length: - - '591' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:12 GMT - Etag: - - sha256:c2f54737913721bc1c2984e1d18ff6e7c21633f61d6e6cbd64d55367d4de1aee - Expires: - - Thu, 20 Jan 2022 11:11:12 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:01 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/987ef070-4e9e-43e0-98e0-2c623607aae1/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqAQ//aY9hxX2ogbaW32nmX01SSuMf0f9p/d916Nmkjcy19fl/FJYYuicgocKt - /sae44rGh/mrxSAPlujS9BA+kFAaKC1mHvIKwZNRIX95XjjOXj83ndEju5DEkWpS10j5fVQ6JsMy - HV71GP5RZpOvOd6h7MB84MtKsKwTNRiuafeRaBdYWsT+RfuAURTHnWY3PpyBFDYwqlh3UeRdJfXu - J2XSc6H/2071WCOFvJqD47fkdtD2ox+pWXjP4D4ZDjNRqx2apSYqdQWmDuPM9cxDbIMbELnoZZ8R - /e0hgHzbEq7bTwytpyZKnW5fdx0MWoE1GL5l9a6Yr8HdzzbOxYO3vYCf1+gQCDX+/4pRQePzS4+r - 7lJGkIQ8ioaX5ow/nDlllLqEXsHxybCI8du+a/DvlDJrpf7ZcfZRGpsOyU1w0+ZTizPfknMaDK9/ - xhhBt1JU4huxZKH3F1F6y9ws9tVIcfk6eVRkWRbvcVIf1W5yPb3hGPwZe8TpQmp4EgG9Ub6ExLjc - S1lyJ5IVBm+MUy12DRUIHKDU9ZEtkCcqZ9WdNj0FeUGiCUg6Q9ODrOVkuX53JVHwbOBMpOu7Az6h - Vb3CCImEt1VKsPRNNIMdJj4OiF0ycUwlIlZNtTvhP737zjX+FKx7fA8WhusxvrxN7bWj5YHaJ6ur - 89WzLagmFrEBFNvz7Y/SPgGyUwWol+H/UJhuwiMxQPzXQZFSMVaf8kNud+FEcsVwLlr+7RxltIUk - Cg8CSW0Qc7K0zX+aT1t1ybpjAxAU - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=2-sixty-nine_alliance-msg.gpg - Content-Length: - - '591' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:12 GMT - Etag: - - sha256:c8d979c2a5ddbe1442b987bf52676c27952972e9b5cfc65e8725808aa0c00ece - Expires: - - Thu, 20 Jan 2022 11:11:12 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:01 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/f2fc98d1-8acb-405f-a4c3-c93bf23febba/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqAQ//ZGSn6Joprv5rISp7I9pxfmNwnQywlsFX1PCfQd9yWWVg0BBVIgEp1oe1 - 8d5CkW840whZxhT/+2RIqDIHZ/sLXJabXXDa1NIYBLCehXbkFvZDTBeyuxWRxk0QPFLlyB8MYN6c - 3MbLOsyjppgQS4wtcYSlcDva5tuYn0wnlWz1DEUAAgC1mfuNa4AjlfEDh6pN+52tq5ysl9vE3WHA - CHAuw5Wbql3NhJgjmWBCY+5OirTUWz+UBX+XhyPVD0g1HMD9mbpbgUFhuBOZt68YNPBdrtosLKp1 - c7PdajSwRqmE4hx2s568npRbFjL9l4GpGAcLef3+hjCfK4kTb1wcIsEcZX/dptfId9Ny4opzos3S - r/v3TckuSbzWkbO4sLgjFxR48vByIvB8DgDPTLF1wFn8KjmRI9uy3+lvjjhQ4FecRceYOkZRKf8E - DOzcGlbcxQMADYTUkikD48fEeVp7GrqCcamdT5xtVK1EC5BgrU411KNV9W98rWAJKiwc/ZM5TlRg - A7EaVllksthnB/R2nt7wYXB2yhi3iFOQXWOXvgyp+TEAtmMGXZXxhOCAPasxiiGk5lssxmckhgyJ - sEZY5vkrcUgEp6rw1afkDpzrcnKYxe/B5e3nxzB4HY8/VoNLuV0qCsyn7KF4QQgeFSblbbPrXGa3 - avOREyv2eBcOX9INYBPSbQFIF34xe1cmsu9LRxvJtNw+7L2jfbAt/p+K0uWbL2iWGAzWOdIz4ER3 - ZGE7ejn1FV5LkUiusfADKIvWh/Jcf4rRSY5noaaUdBkyT0JDXWLPvbANUZPIOysB/tO36MRBBdTF - fq8mcxnERAHf5Ok= - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=1-conjunctive_lavage-msg.gpg - Content-Length: - - '638' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:12 GMT - Etag: - - sha256:369cbfc86fb18c430582307d6f64110de459504027b3132883d89ab50bd50ff4 - Expires: - - Thu, 20 Jan 2022 11:11:12 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:00 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/4abcd4b4-3922-4ae0-ad97-9186f51e172c/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqAQ//bwoOwi3Zwszz1n7ylgcD++Vx2S1yUzLOqNi8KWe4xAJSCaJw39dcbkiT - 1OqJpJDWwIjWd1yRIoeLqH21SX4+PWt2Ra2j/MqjsnQdmXa4hEqdnTgaiLHXC8DvUF3Kk4YfJ2Ro - e32INfFkpT+AuXRSZFTmVlmzFYKTEvlnAGhOGubEbZPc0/pWZt2f9FlnVbHGTYeiD7mZfxmpwVTL - ilTxm0nAZMVsv+sD/f4yLoYn0f34e3zMwWgWFJ8n5G0Avnhkxq7NmzOLeAIcmY+jA3enYAUrhCNX - SXWgI+sUfNh9Fxyp+2DkXtW3hEctclLyIpSmRbMSfhGdUbGSDlRwyrZXZXvE2GkE20xiFbilnhjw - dIsgCwGWjIHduH5S84+l49bbAQ3lHnaQUzrIBM5CAipsubdp4UJQW5MH+QcEf6u6P4YS9PhRs6c3 - oFRoCAvY9mRSXe1iqjxE5jAXQeKZkZGzB3AJdoBrzM6ZsOFXPALJy+eKk1/k1NrR4md/MUtAxsej - V3CIH96BC8GUNMXAaEzHAd7aOEN4acdT9QY0uua9cq42bJ7Em3zpzxG7x30SLL9eHvYuGSqeJr5T - K1HF10GEjdQBzpR3PBl0eFwO0qjqW5YBQyHB4+exT+vVYJ1sSeOQor5yCFDDxjplYDonYeQLJOWl - fkg3UPOpFbMvB21nCRzSigH1RFaR4mU110vETzz+BSfNqDawJdGdtsvgo/qjszTVhRstgSSMRJkP - Oi5gpNSjAKP4oHwSf1YS8EPdA0lnR1/keAlNkIMfogWicxyzegEbkFFVdvxZDw++a3rdFanSEhqn - B/y6C4BhoY0kF3V3RbHUG4xB2voOTgdqbuB34EjiXqg13epvVzH5Ng== - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=2-conjunctive_lavage-msg.gpg - Content-Length: - - '667' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:12 GMT - Etag: - - sha256:d92a7cb9901368d8ce9478c1ee67a9becf3789330648c801de9070b5d1c38232 - Expires: - - Thu, 20 Jan 2022 11:11:12 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:00 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/ecc07e49-be88-40d5-8e99-bfb3b3812668/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqARAA0bqrq1QpF62ZAMgrtbCo/7kmm8IGB/7Lddclop2NH0P4BEOO0yCFruoE - oh/JvsHnA1aOiB+OWUba0jqytICNts/SmkUCMGawCvB4f0mCFTwqnPKZolol1juhi+v0Nj0I4No7 - FL8hYgu4OQnUJoUaHnk1G27QayFc8bpA/uIqD3Wc7vy1stVmjIbwRZibEUgUThiW05jvPST7bCcf - a91lPAOpIB7n3jY43omHBfCnwXlhCmkl5ruyKJK0a6buP0UlZJv0eMNjLJ8cIZmIabOsKYJT4JGD - fXGJ/NBOa0Nv++crzLYu8tL+8iApEdyegHsKpzKDoT0t97IemCABPjLi18ZRh1YRlrOPKSre0HeE - 94d8fylTU3gP/j0oWt9tDxhMuLyqAjqfB5OvwNyO4Q44UovqnLdiCQvkTKavmXlfIoQ+mex6jlbD - AbPj5zwPU1ms+fqZ5BMNWagpuvGpW4+uDG4yQCbwKq0OWtdqMC5Ml/NC7bTXdowAUTZxcK4L1UZv - 8BliQ0bS8jKsFLC26KEdO9kHYwhoUVhJI6sS8IFTUBRpfuw7sc3ucjGC9a9Vbfc2ytTnSA4thwcn - 7kE8ElvDn1lpOx74+EeoGAksYQTw77FAf0OwYALZ0MlahyzxcZeW0WUShR4nUFkfwSghPmMYwmOW - NgiAEgyTB9G474RoPLzSQAH3kq3MXakzuGOxoH0BJyCV7pjx3DdpQxlg/PddYwURy1JO/2aQlEcd - dDew0WaSU00mRSf187RA0izsOoPJZGg= - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=1-indecorous_creamery-msg.gpg - Content-Length: - - '593' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:13 GMT - Etag: - - sha256:36167d9be8bd62598eecb1b8cc4f7cd2e6571141907ab2ff46a3add6c164fb96 - Expires: - - Thu, 20 Jan 2022 11:11:13 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:57 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/c60627e5-dfc6-42dc-8874-b290ef09a2d9/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqAQ//QX+Kk2k7xQF0Izm5HeQ5s5yL46DBQOX3HFSVih7JkpcjVGWREQyAfnOa - UgsMZ/sxJzKxLK41rRDMNAX2tWevCXoJdULFntJ1RQkUhNcqs1h9MPnavQxij9qSmaLFiEcfaSnk - jBooeYToIKaZ2jw/krVqqa57wbQlEexGMc1wTlfstEdmN3sQ70bZesNXBN7Cqv6HpVLbwjhhYXnw - 3mBjrCNwajvKVTW8kZvW0w/bufTewd4HYjycS+LlL0vtm6gNS1L+6FrMHktMjKyv0v4Fb3W2OQVu - hCVWvXccSY7Bv6cBNhiQOu9TcsR9MYrCSEBx7PTB2elznj3rcGsI5NTTcbt3mDqMlqSzAFY6JggH - riUPbNiiVwbGuMq/1QCpuHm7fSuLfxcEJCWbMhWBiYGbx/q+0YuuVnAwq4ECpo9OU/pWawUS7MqC - E2FktiBBlWJNlU7l3uKA6NpF2Reo1tsdSBsSBxg9JuU8hmein+PQtDgiUfqxb/z5OynsbKgEErs7 - 9+2uWvTzZB4N/4D49RcJQC+SY9rR6a4+bY1acVXF6lSDwvgrmdhtYRLh206Kk7GLyWWlW38EPB1v - vG51N48usjrAIUZGwyftERf7eZyqQGQeGCEqxBkjnTwACDUuEwNFuHDcEPgE7wFlM4vUzqnvbJRL - y9Xh4po9fRm/aUGQ7QjSQgFGYkMyvxrOBNoz2u8GYFhQcOZsBwx0s/pNwWHzjtqTFWu5QYG6kHmz - NOMplDrqSg18sbLUra1CifTy2uGLP7+EUQ== - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=2-indecorous_creamery-msg.gpg - Content-Length: - - '595' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:13 GMT - Etag: - - sha256:49c83b1c967bf7f87885f8a9e50e375c297ffe1a0f4b4369775f87a1d761d5a2 - Expires: - - Thu, 20 Jan 2022 11:11:13 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:57 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/48bcb4a3-6f23-479e-a718-e0b93fd4b9c1/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqAQ/+N0q7FdEEMxFB+ckGtjSjsKZpRrDlSd9P9hQNspERIrjrUL//aTlkRuyC - Bf+MtKJwjHl5QQvwSCmK9j+6tx2r1mtVBAvjB+Cd01Hr23buxhZ2nILVbCjq4lNwdWbbxYf1B2BN - VC38P3+hzfoToDaBYqPY8o98XeHxcn9ogqg7BXF73lHcum1A3Orq331qzrdnd5Hc0uk4euCytLIj - HvLLOt1fahV0sem0GwJjKgKcw3KNYElUipL82TUvVXmM4oxUSRbx7c1qvmMHE3RAvzMmevZUV502 - 5hzDJjtjbdSjwEQbsGTvmAy8Hu8nTIKmqZnLUNQAeNMLUiS9P/jy9eXn0EuOyNL7IcAeFZx1F5M5 - VekU1FiIFWM9ialJT9+muMkDUsgZqaCXQANzNyQDOvankAfDwLJYZtiUXCXAwI5QVzK9PmGotWii - 1DLqR1Rq26WKe/trbztyI+22Vkow4IJVvKSlzFftnDML3C2GnsAbo5+vwMBqkAX4F6m8VBeeMeem - ylDCh8bq2BoibodzbopQsKPZHcbsD14Okno7moKH3OFUReGqi+a7GDMJvN/XkEIRWjTDPnwWlfIU - rXZzpkZCwwDgrflLRVQoUBvQ3gu2+4T3/xE0J7kEFMR+qjlMUVCQFIQAfoTELFIlTOaN9a4T8Xg9 - l6XTUfpvJnz0PZ7s56PSUgGngyQhpYO4x6gHOBLO4+OLJSYshdB+qNB0iTLoJwjj6Spe3u7TTs34 - XQpIPp466dFfsJclGaqGodCghkn+6OYUt3pMeTxX61meRhYjpgdceLE= - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=1-concrete_limerick-msg.gpg - Content-Length: - - '611' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:13 GMT - Etag: - - sha256:2d4f3f0281c2b3da41855bafc3c90d3c1509d7f7b2cff3456c55a2b7efec5e31 - Expires: - - Thu, 20 Jan 2022 11:11:13 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:51 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/d8db9ba7-4789-41c8-9f7b-3761a367816c/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqAQ//d0r7U80dRHjHvMi5LkGOjtP+uHC46RsTkcshCNSH6++lYRWF8Y7USW4x - 66I8tWPIuuCIs9GcooUKO4b0kLz9NJlu0znbaIJN2OPeCJQ4GsQg49aPzTh6aRtOVt54sr9Lzlgu - d75mTqLtgMriTPKg8047lTxw1430feJdKSXIIPgce2S36CPPmS/yXYQOLMnsdvnpJ0lUkjSU27hb - PnF46hXehR0MKUArrSqeKAdOGUfkXHW13Kzss8tEvcfRlClz9gHePp2lVSvN7Urq8jEwt+EAQIJ8 - EKEGMVgdu+hQenjoKoubG0kP7trTg0gWdYP9jfprQEznCFIsDi7H71U3ek1o/eZz3Se1gkrxTDf4 - 3cTIHRjdw7szTjwO3jGIWe+PslKpMvPm7xxDI7LUk/7s4NIlMIPmHPEWOek/GrwCf5yp0L9554Ti - 4FF4LQwCposVIAmN9Haus6iJdAj3Br17tbkdW+SQmuZ9goRSotlA+mCMLDTIxnPKZItn53m5zHBy - InK+vOdre0gmCs40O+z5u2TPNw4SflxvJbk7v/jmoWMcRlURt+JajxpNPko6zluuRxJyNM3Qn4t7 - gLHmYIKMwjpr9RdHrPkSwxQLzAcW+DITCl6crxRTibi+QQIEz5bSf285lwby+66xdzgqX663KH5Y - p0dV99rZgiLwlpl0PHLSwCMBS9rTj0edt0rrwikTltaCqj5aOsOdCTYH8SQeSOzU9sreZbrLLAJu - ca+7tsvRFAQDl+YvIxN9UifQI2h7Kyma5F6EGOQ+OlAdpPFgtN2lKnX/5LLIaEf3M4uU+BPX+Rem - fPHbDPy/szIORpdcLA6z7AYk/a4i6ngzmBdqEGhXaBqkeVItHR5beyCcks++evNGECfcodK4SLDA - 14pFiLtnOAIa6GzJHpI7uiK4mPUQk+2ccMP2pdhpt76XVpShKkvAgjTexaZBZ3ELKwQDVZOOYf5d - 6FmaxpeN5Tx4/hQ2aN0oYA== - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=2-concrete_limerick-msg.gpg - Content-Length: - - '757' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:13 GMT - Etag: - - sha256:9253415712bbff3a68beddda5f93781c81399d5639f7f14a93b49c8fd8539ea6 - Expires: - - Thu, 20 Jan 2022 11:11:13 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:51 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/submissions/7e2de803-ccc1-42d0-87f3-76972745d11c/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqAQ/+LTnLpo/pLzl6tUqLxckEJCSe8zdn+H2XqP+NOQoZ5pcmzqtPjPDI31fv - ibuvBSE5IHzZfvg3X/wNkE1s1IFVRf0kjC8jcJD4MZX4bpyB2uQatoovA1X9J6OjLjoBRbEseRfW - 5ubE0nxFpdCX3XvFDT0371u6GLpi4Y0fsfC/Oom6XI3waop59NbYYqi614DF1GIcI/vXo9B4cOnl - bkuSJ/Sf5+uZnwEhDUkTuFSnfIHWfTP+ENeXCUYRqu/w6dEqnVTwVWWdwQL88Bgvpuif8wCVTA0w - SmX8LVnhudWxRCnPS7GDxhV1OiCRvvOBx80Isy+XXfoTf/UiJbP/zO0zF25FFS8jIWgHxiqzHFDd - QY1cGTwM8nPciaiW5PPj0ghlv1TDyqDIbl+QNd91dOPVqxFt0/EwT+RA74ukHmYbfFnE3BGA6ibJ - /brtdNcgwosfgeyN+9bI1rNUAPWMeMb2qnuQn3KwaYfLSv9hOxkVtE/xfocXdws6zqgiKCS84mHB - zfoeWSPKD+5pGxuR0VNNPezCWRoAuSSeZ7YUEK4PehfV1OrWo9/eAlvqzY/wDMEdGP3aaGLrGesH - cNGrfawhNQsndIlZTf/KTaFxSXIoc/BAP2l+GzwM3JyL1lTQp1d/nIdeVoq8Qfs7EWnhUiWy+03x - 2fEfBRADY8tKxtLoP8bSXgFoywsO2/jD8BHKxf3Bihb7bf8inYGjdVpG+uPyyo1gy9jg7LcNU764 - mU0m+ArM/b5cQa9jmplYDHL3fZ3xuCfUgldu2jvuErfhdkPxZ+F9qgPfYFrpjKbxsE/V7QY= - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=1-consistent_synonym-msg.gpg - Content-Length: - - '623' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:13 GMT - Etag: - - sha256:1b629a42600affd777665af40e1324db3de989f51d0ec3943857461718fd7acc - Expires: - - Thu, 20 Jan 2022 11:11:13 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:49 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/submissions/7064722a-8970-4fc0-b8df-8b8c05a95d81/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqAQ//f06OY7TdROea0h8wAPqHBVj4vLBLKY4e435urytRmWqQI1MnPC2Du5BR - Eb3OGYIsZeuYR27gnkxXQxAMUR8R7NWCn2/6eTEQHh7YuLxIHXFs2uyPLe219sdM/9vPhlWjbET/ - qEPsn42WKW2bFZFvv/Not5ouEfn1PuxyplGaFXKJ2i96pziQ+0rBFYU0Gc/psQ2qqUYT3fG4lCGy - Poi8Fnken38RMRYh0cM/hesB1XlXiIDrDBClGYhmcN6h61Daqgo6Z1k4HQfsDO9B6PR8AQ3y385p - QXhzMN10p5kp7aCRbFCqMgd+eYWWD63NnqyB3BI421tZcULIXow0/ddkZRErg4iUnRrqY0ZJKxm2 - PNAh3B/d6LMyeO5LAC1K1xE07ZAruGNCmTpdC1xXLSoSbnwLN1ORjtc+2ZR60voFWkmp4CgUA/mk - zfFwf9WYsXFPSHTIH007M7LzTFU4xsKLqjoD62z4HBQXDtpfLdXY3Hdb8ybdV68GrCKXY4GytQpj - ZSrHlpfTzaesyBKQpPDkSYjTlrhPdfeE5c41ny50zqwMYMrI3uyrVBdcFyaoRs8LrGqgrtigiUG2 - BgVGwPEOGbpjFQ120lnLS4mvG0M/3oWPOenUJayNhRAXesB9mJa0cLC+9xvXzJXs5ZKH2ZzxB7wk - wc9+9wJoUa3fYiGV/UbSowHMr6W3J365h8lkRpclFeQWogkO8wMaoRzuqFwe3DnMdcQjUG0rmBCi - QUbynFI54RiEinJNDDIVzDp1qx1TADMskGMLc6/vxT/JB5lGBK6ueXCdvCIoQrcUdkpOlvDaFomM - kLQCAih3421QTr055Hz0tAHvXn1nqZHYSh2Njstra1FzMDBlI8yaL28HtgpMr93hShTJwq8dzarq - SI4U99qiJHw= - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=2-consistent_synonym-msg.gpg - Content-Length: - - '692' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:13 GMT - Etag: - - sha256:8df755c2ad5b82e4c47c0564176df0e406d33e444386fcafcd7c524b8b558467 - Expires: - - Thu, 20 Jan 2022 11:11:13 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:49 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies/4dad63f1-dc12-4162-9c59-065c88b2a8b4/download - response: - body: - string: !!binary | - hQIMA0N7bDxphDAvAQ//XuxXLagu7zv1n7lcws75pYK8tSmE5tH3eqDw9imBkXqOWtutqRX3E9YB - EKvcPoTSZwAxhU5vdHuWHtMbglo6no6eEyzVXnSUHUzr4Pdzv4uL+0prIX9q1u4b30qsZ6wmdIOt - KkGav+8P2ifFfGvleyCigFBV/ipIailap8mkDIKvxGRmAmCQqCJHiUpRNe6QkEddaBLwdcfOzubZ - 4XxsaGwYo0cYK30+NP8LCgnDtSv7la+mtd+qHVylkascHnGL1nHP9yFbGTxKZ7RvlPixo8qMc1Y3 - INLmgKyOca6iDyH5swWWEptE0AU7fPi8ghDhtXZv8jEknClZM71BHF8YkzieeNpYozvhJLayQvV+ - sDDwe6IDn/hDXJtYSNSa0XHo79hVQafknZAfiMXBSS1LTsCSRkcSHvb3KHoe1s7GqNprbx+p/49T - MFHo2HOJ8/UIcCFM0VoB0LhQlzcj7vORQSNrDpVS3AKgdZPsJ8qpsjLTeEKszU8B/GPbBNVpAuv2 - i0YwAtkNN3nzOQE2Mq8mpj+SYS/iTSgJFs5q6VKN0mwf6nu+d96BteocdQrA27aSMXo11adLbReS - NEUkBjRL9/sNl6d4qGCXesp3DZym6pA1Zf7numhJmqVdFHy+XgmfSOZaSGHBDMpt6csHtBa11mmB - 1w4S6WN5e2jKiVq+30WFAgwDw+fEwKIgGyoBD/4khdTGj/2wC01WQJ4CG53Z8e5mATqpPjBJdNKY - Y1OfJXRZLKdbNvAu9MLzVlQlHmVZkadmierHaDStK5prpxlQHZrrcuWrRjZZhRd72EujVSVwEHP0 - hEYleON7I0LQlc7Dac812iw+Qzfaqk9AEe+0GR9xrjsc13bfLdplVK5g3mc8rJMPbK21L9c/5JUu - tEwMQNN00sbdhqaQ38tAqcGCc4CiQK7t68PnGxpiD6WqGng0v0bjpr4m7l4M0RGix44QFuMh8fOg - ysNxdgikEjwcIqwYvuXYJOJKvl/B3NrLRgSjc08HBYbBS9731ic5UGrMXMb489Soey7Z1K/d8paK - fQI01En3bxq9Uu/px1+W61ckFVxnuJ8SkM7Dgb9GQiG4msoB1y3SoKqpbq9Ny7ZETfIcneG5eeJ0 - e6IvIwKXbEamUBAK91p0FPrNF0/x0bea7i+9topmiVt3N5FweHRx/l/iqWUkXI2Q3UHkd8Gelp3g - 4TEs67qGeM+BwIgIuy5PLMu0ajDjSiVjgZ2BQsPYzwWVjWW9igInW1RSaV48qe4bsgRDhreUllkV - i0qNnwZ3fj3XURBPYdU4W+dKaD9F6LGF6OqxG/M5tR2scjOlyCB5K4qnh0VS83+UyavLndBt7W0E - 8n4aqrGdVwmnSqzRC2WLqxwhlkPkwWRWvuJRvdI+AcBdl+2EImV99JPQeNxJtsoYIeBDmYSXKwQu - OJSgU9W+y7dIlve7qXljjmVYqZ+n789KN1w7J6Y1BxQfQyM= - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=5-sixty-nine_alliance-reply.gpg - Content-Length: - - '1118' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:13 GMT - Etag: - - sha256:a37f717849486b9aee64abb4a643ddd68b1113b084b1877331662db5faf2d4b7 - Expires: - - Thu, 20 Jan 2022 11:11:13 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:01 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies/d5b658be-aabd-4d7b-89c1-51de7fa246a0/download - response: - body: - string: !!binary | - hQIMA0N7bDxphDAvAQ//TH6p5AOn1CrjxYM86z+RMEqJA3KAWtZRfG0DN+HrRi4U+4jqoRkNuScK - jGMANsbTgKVFe8ho6dS9Vx4YFxcAxrNSRnOAkKqCK6EzSMXQ9ndwhBGTfLQDsMM8UCQTHb05OSyn - MUxwFS90J+WcoeAXimrX++kseH2p5UQGxe1wDooQqSvDJtPuIjYCnpWaNvp72/z153ihGAZ/83Hh - vHC2huc43vtGLKNgYYH3ZualcGBoQVbCGSLxVukaouLC2sqh2gqhSinEUdf+A62p66QexT5SqYaB - AHt1FhOtUey+LKaMskLv3LZc6GVr6UEEsybveRMgMtYwLHIkrKYIB1NQde1W60nUEax9MwKA4ZqN - 1ArV78ssvbVzAFcqfvIuHlXfPXOmD7t8yuT96hTNAhe2Ih9fiYGVhHAbltP/d6lCzFEzvEve0BNj - xwH31OrmzsrGMKTD5xpjaQnJko8enAK9/V/s+SFevWJeGuzPUd7M3ymD4pGXzWAw03BGK2B0+YOZ - IpAoPKbh6Z8FlBL0tujL0PS77PM4s7kxKZ7pWAU2m/PTJv57GtBaw2t7GTpWdFNu+9zx2vygdQwe - SkJpaM7tgonvBvbwyqT2jYbzqCfRqj45AHntTzEw3UZlxLmUvHh+u/LLPvn7EDOPtl5UQANgj6Rl - XnTgw8k0znG3VRJ6vfGFAgwDw+fEwKIgGyoBD/9pw1xQzuUiV+uEuopup9unQa1XTkfL6X72Tqp5 - eCvRNOHHYmThZCp9QHnsJm2NBwHyZfrYgzl48quf86iekCoPgyW1RPTUEGDCJjK7XvtNULsMZB4m - sDzS32TgP5MKzxGmAwQWTj7o8s1QXv9gy2wr/GpVfF6mbHtWALY+fovm1TkQ8UGBv6j9LZcBjqn3 - MZfZnCqwOqa267ToB5AjxbL6X756TMaydpJ0MCHhh2JcGYEKzyp67BON2lqF3pYfaw/E5u+4N8pc - +H5N1E9T23xANWJhiydk+BE1I4moDVTR+iVn3SywDKFqO3VdblMVAEHS8ZS+sTSXi5KJw0k/+v5+ - Q9j6uKeMCSjCwGInby4AQnFhlKXL1hBaYFVAjHAaXZZhGrPZOErESOJAFCGW9WhJkedsi9HP0FUC - TuNZpJB31EDo34+LYIrfBmHXoefL1vwJKHSKR9KNROiEUT0hv6pK+psT3jXx/dCM1H3Ads6D6Rc5 - 1hcS1alsjXoWZJmgugON/U5WnMvDDWlKtgbHZQyelqEzcDvItemBqWNLqfrsDJ9wi4nQiEeih/xq - /uYB8dwYMhi1sW8R4Agn4hsQhchMtiu7sFqAm69KJR2c38x7njcZnym3mEn6KS11ttbv5Q1kBRLm - O8c7jLtVxyxdwUGIBsUfwFM+xQq3cGcZ6Dfdx9I+AbOZaVM3gHy0lp3wxwUiEVWuyRG/1/ys8jlG - Y7W8jTPskwLJRay6Z0wkCcGMYPKnvyIuMuv9gaU/FluEaAY= - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=6-sixty-nine_alliance-reply.gpg - Content-Length: - - '1118' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:13 GMT - Etag: - - sha256:506b499968c47ee42d2aa758cf2043499810091417f99d4bca76a2aa239d5b52 - Expires: - - Thu, 20 Jan 2022 11:11:13 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:01 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies/f774fd7f-55ad-45a6-9a92-05053f9628bf/download - response: - body: - string: '-----BEGIN PGP MESSAGE----- - - - hQIMA0N7bDxphDAvARAAiG+s16Vbg4K5FlEW0uWcJo7kNeIpFZa01+NEF9IwW21j - - VVP8spdAh5z2tfAsEFHr5uQ/rT0PJT7EfKe41x64rYnsTH8daqdnv6TFzAhH+/zb - - SmyCt5uvPrlvUJF0xXpHjkolDn4zg6UTXKEoOsNfMObXgzmMFxIyJ8mRd7NcOlkB - - yiOT7Tda5ym8gJ3iSnqk2q9icoDsesHI/NvW3UOib0RXsK4w/9GK7LIh9C0ojV7U - - 41eoRjZuN4ed+B6A9URTN6e6QX9afeDh8vif0aGa/ToUGVd4ZhPYoYJrXcUQc7Q2 - - UCGt14QoTsOh8OMi3Re6Z+KKELy2FAdhbRccoGhK0w6ehajVniCDEt03/KqnBCEs - - BPhEiVpcHPrDqp1Il9mOp03l3DkZtlnmBqLG70KPz5SiEYy6GlXR29fNYrNyGwGY - - 2Kut6J8764T/2qKPYoQm24N7rMm/Liy7tfQC4GIEgAKFoFfvbbmES/WmgYIzpHy5 - - gscF2pPKUINDQYVSpkDo2lEvcqDzywo/Sv9GzV6uJmXFOHIc8sQbknzMnWiPJ0Nh - - Heky7XCzanCLyfHCkg69j2EAlVkSxPK/xIp4S4UtOMdhmzyTQc/ogRyLRMXZRm/a - - FkQFoJp1m5quMK4weBTwq+I+VwOP6OJXR9ia6fh8n9pu3TkcJQ7aXvIXgmmWq5GF - - AgwDw+fEwKIgGyoBEADdkW7iwa1Tu/b7WqipYFBtAfQQaiXf041NQrNy9KTZkaPQ - - xEfQxmrjVPlbt4lN7Ldsibz8Q5qKVvJOn6t/SF0nWKFF+MOGA1E+7JXDMg82c1gN - - dS56dFio+2GmmQjJc1kGn7Qpn4Q61n9jy598vkeoVJrXdeILW5eycFInkf824p0L - - i03Q6nU4rIAzMz8gVpZlGbzbT/3xsbpz0uhiPHVYUT2Ry2+W4q4/CQzo9oxG3/i4 - - kIZs09z8as7PHqgdwnnXe055d9/4phLfFsCACpDuktryvcFVppdBVcov69AzjW5N - - 7lhHuAdUnspPLw1qqLnWNFnWrwIblBzLRIW3hphRS4/Kwwxmrfo3LMEjJaHT4xWt - - zAkWnqoUtrMdl7xp1V38xabDNYKAckbGd+rx1ZfefslPgfttWqgakpGWLa/vixcS - - RUi38eFDQmefFtk9KZCUEl3bVd6leO9NG6TCpci1bL1oBH3/aXaktEst2rvMhx2h - - TUK31qUbX2SLXpR0OHIPgmjpN/KTt1zj+52s7GxiMAtpPt7GNQpRV4Zw5Ka+fBcV - - GiLkFrXPv4PLYGmvoESv20Y+eoYO0jS4QKVLeuoUmrHyHeV3SnN0rE67YnboUr7j - - 3N2wjAR/eiGM1i1uDousNkkyzrRGD+Dc2aZmpQFdckyPB8ZmnYb1DlN5McF5vtJT - - AZeUU5EJgP5oNSJHK5SmCTb7hjT4/C/Q11APLlS8ZRR0qwtuFHTFu222KMPNH9uf - - Dsw3HgSs3Cwo55lbButmAegxnnUiGE1/F1X6ar1p2MywymE= - - =Eo11 - - -----END PGP MESSAGE----- - - ' - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=7-sixty-nine_alliance-reply.gpg - Content-Length: - - '1605' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:13 GMT - Etag: - - sha256:ff5cc185ef0e96a571d94298f07b2046ff66788649d7548bed771f51a7ca7bf4 - Expires: - - Thu, 20 Jan 2022 11:11:13 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:11:08 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/replies/158dfd73-3cb3-4a6e-85b3-f37ae54e0802/download - response: - body: - string: !!binary | - hQIMAy2m2NzuNpRrAQ/9F+gtuJpPO37A/NM6OacHAK+lBUvHM8icpiAz35EqSbr4OnnAQ8IRX0MU - v8Z0QpNB7+MCWlWY4QL59zaBuqHwIeg6GAu/szkpRxhD5eKAvRa1ukR9XrQ3pDmpNHU7k0l3x+jI - tmKqt7WtxqiZ2GjIDTitpgowd40k3Af/BeYQ7IEHqzv0xbpsVp06+RtLFc05Tg2mVlK9lt5mJmht - VcZQJJ3P+d3wcROuKuwmPqzi5FAlLQx3opOy1hbukgpH4E+lBSA1EwsYZ91/4AgnhB+VLgw1EAsh - SSCtNfhTE5AAaJ/a78zf30ukkZ1v+mIaoX+MFYCk0/eGVQpuElK2OO3MH8lrOylr9/388cP+aWC/ - iN7RpXdUDWi1iUtLLieBwyVYTNnw7yea7Mbpme9gwjk0Jg56dgs+npUWLp+BTChxWAR67nG4M6Fz - vNZbclyvwyrojcBWKDnP5zIGIxGFufNeJcAehapP1SVuxuOO5aCwaKSZLiZZeINDhn7qJ4rNNhja - 2fwQbVmMW8WMh8m0ofijC1mQEj6bh0ElUzkZlRcD1WgfExnlyHov8AWu107IidLqalAU/rAGksd1 - CxxCUZ8cixPktyV6jE+g2IMGD9iNKuXmlJy20ITvVpaq5OHT8lUPJIMyoZCcfbNJy4ys5YASATH0 - aDU5C7iLg3hWltKCUU6FAgwDw+fEwKIgGyoBEADbIZ0faKpZjWxU8Pu6ZGNEphU3jYPg6CT1j3M7 - 0Sc0kBu3WZZDbAH3wUPbMCD4xNnTWhxjBCUmqLorPXXXm2LpE7FaApUS/DXl/TjTdYlKml+MsXph - AhdQQs/P6w/WhiHI92UAOdWnAtKebjMqh23oaFVVuVdkdXEdz62aSOqkE5PLJ4EggzaAEo9hwc3H - m/zq6f5bxS2BdgnEUuL+4Q3iOiydQ80obTJZNIRDPL6cmC+XKDrDA3sXluviOA3ct8nnwtwtkSGH - /cq81wt9lNVxpVriOZfFIe74bxJ3PQvxaLGpcqFg8nT57bfVzkhfPuXYh5AlNO459RUkiaZa3vmZ - ZlltTq5iNIrlTPqX6GerzOCHYYu3CT64DgviXF9isKgukzDyZmeGJK/LKSG+uC/CuBSzF1opE6SY - F9B0sUTTqPJ7mBmJU9wpoNnQG9uGx9/qEqRJ43k5KNGLUs8LwtqBhKkBNUA9HnasfjYdDvhmNxxk - ENr+Vg3IWqwsCrSeaOI7BaYiokDpympu44q5NZ1f/akfXjdcdO3Z7fStB3lOJX/ZvVRcZyg5fkXd - wSg5jQ3Nqyq1ZxTkuUt+QHx+74VMQXJ7e/w/OLrJNoedgLM4eY+U2PqhsdNY0qXQAU10eu/yoK20 - IWQoqBEDNvKbs8T0zTELQ8Rw3527ujnro1cfoNJtAfJ5dQ7MOzrxUSNXW38Y/O2idXYllsvRNodt - kahbwINUfi3i91KBHXq7wAdQ8wODMmyLXZ5tJCbnpkHrH9wx0/Q+W8omR2zjdOgD298MjO0f0wAR - 27+cdwdzVlNEWsvI2nIr4bWhIq/iEq0ZCw== - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=5-conjunctive_lavage-reply.gpg - Content-Length: - - '1165' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:13 GMT - Etag: - - sha256:6fc20abac42bbb6e36d08f16e84de997605c3caa88b1b6610cff5453f0a78bd2 - Expires: - - Thu, 20 Jan 2022 11:11:13 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:00 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/replies/24fbb6b4-504c-4fa7-9971-e6f2d1447a48/download - response: - body: - string: !!binary | - hQIMAy2m2NzuNpRrARAAv2fCgqOcLQn5BgYTSajwFM4sm++V+BFhV2RMZ0Ywc7yIGObndNc3H4v2 - 6CFo9OdMA2+uQrRzF3sNwoFn1tFLkRLZR4g2c0R8cynrB8XYgV2dR+T1/969ZEfOcCpFVOeAl8tD - Mld8VeC2HIiz7ttYMnRhO0LSuDEegI78z2idd/ugDgJa6oDCdtC1H4iFWiyES/arZQhlNBonZcJb - K9ujj6KWKysqB78+APhIUBF8DuAhRFv13raTqR+y5YZBJoGLqCt/K37Gkj9oV2Ty/juFBKKEZgiA - wEGgIYY5DmytKgErLRIZhKr/mfjeSpAgtMLFp3MLH6BXASzbGvUZoVmPcRcg0zujYARWu0cj4NFf - tfEHO2qqW0WQIUhzjEYvQEf9lbu4hZp9tNJ71hASCXJpVMJSkazq/5Xnh2ukFlSpvEaSOl1nX7jk - 7UMHQFd6ckTIssp7aIrZmBJB3kfcGxSWkCmu05fMFDr6LfxeyfJlt7kDv4PP0xHaY0A+aJ4Pce+s - WSlRkl6akI0+ZLsADxRNq1MwSVi9G9wqgoJ64CUJyjo9nMWZUyNISx7bYnZLG/0RzS57N6iXQkwf - pr9c08+zL360sJGnJOKSaAD05VCgduE+EbQ02fd/GN8sC7pJ7vc1bFoOssmIHjVtuJtCX1hxXuie - wzWk3g9HLU0Ge/P7wHiFAgwDw+fEwKIgGyoBEACzLkBPhzq0XbOkNrJ0mgsG6Te9AIHzZMmCpSJB - FBBaGUwkJP2njofVnMzUzGZEiloNlHU0JqU2h+OygDwKZWopcnAvjSf44nSXVLariWywWWtRrTUp - /qLymnpIEkK8LVrwGKwNhavEzg1xRM0FadGTGPOpHhm9WWU1cVU+zxy7JD/RJCqByXhZgwBnveK9 - 7o7/8MtANWmmEK/08zzfRKJAUDjReQFlbyTLtTzLhZ5qRapDPMHEc/5iE0FyArfUxmzgoC8abvuR - xXcE/rqj+jXpekfJGnh/b1KSa//3FU1KglcEN12aDT09hfYZLs5aNYLfhRGCsGUwI/sGhyr7fTEC - swj4DcYhbRdhcMn2LvaLLxHDzT/CYwniLzryFGN/yYFqoWH4VNK/k+fd63ovJoz2gvTOGtF85bKP - D/djVUB8ZHrwQPYhmVPAq9GgE83APidKDVpiV9o6CoGc8lNVnUNqMg1m8OQd70wxbSNQR1UscTsv - pafXWb8BGCv2Dh92nGgYDsVG4Q7kyxacH8/6b3Ej0NAxlmq7T4KEhtK4zWAxNW98fuXvU6x/xOed - GUyIJcC6LRy2nvHKpebo+x/m9c+z5kL2IkNszDrn6K+v6zRge5KjwB8ZVaQWviVOCO4XBevHyBM4 - QUTOhwvaKSO+Lfr/d6SUkFeXPW4DszXo4aPFPNKKAdRQneC2tRM/jHptBBJcUOh30yiyVZXtqyWJ - bUWisJsylbza/CcoxEe9YVWqq8LATiXuOiIovJw9Hl4PowDN/a/tzELxzkEvkSpliChiOETfCBtz - sUrPgThyINfRHpw1vW0URz4mXgArtxIVXf41HDU6Ks4Jk6dI2ZV9RIfHvP/D0pXi+cBES5kf - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=6-conjunctive_lavage-reply.gpg - Content-Length: - - '1194' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:14 GMT - Etag: - - sha256:3d7492dee4392a2c7180f236615ebd6c26d772529d502c5124258127ef40a391 - Expires: - - Thu, 20 Jan 2022 11:11:14 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:00 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/replies/1c2ff7fa-252a-426a-83e9-5840cf657739/download - response: - body: - string: !!binary | - hQIMAxGWEiPHDepYARAAu/TMRu3Ff5fRgQqO/E5Bv/94dfp2b5I+AyQ5+ejoEVp1xxS+IiQWM+Sn - YWnrgUSCRlPRZLzlgORkyg9hV+Hke6/ycie75w4z5C2yLMp4fS2/bsIsAfUpd4diUUjc/L++RWvw - GX91oQB9aFsEJxiD6LIb5DvXf4EeU34XmTGpTUNx2st1bcTvsw3ApzsW4isLgZipHKYekOnX8qvx - vpOjVjyWEeSdNNQg+hAgB9JK+vp4Ueykhyz5Xg6EaPbWciYV/pgP4kDa0yilHImH+eSABa/SKUar - ykt0ny6BbbyfvZJXCC16sHuCzmddXBuhoEm7Z9dn4cBbP/mWVbkw0aPTYEdTNYMi5pMdVvSWlLbt - u8A2wKiOCkzUkaguZjbsJVJPc+jm0XQuccVqTdQkUiXiKZWw/pFxgc0UgqiHF6cqO57xZS9I7OQs - yx2CrR20ITwb2rRUxsF5SiUvGN39aj/2ycIZ5PGZ3dweQHDOMo5kR47aOph2Ac2BztN/s3x7fqfJ - 8KVjxCW5xlv9yhl/lIr6CPgH+4NqJvxQu5M3zXVr3hTnoTnBoLX/g7w7oxEwAi43jI0FEzm2e2bn - W03ezM3b1P0uLeNx2nmqo2HDZPJPItU7BgN03A8GBmxPsDojeR0khzZtWPBPPxIyELg2I2gPvDo+ - hQI5s2Zwu3b1jYnq012FAgwDw+fEwKIgGyoBEADHptlGI/S5RTU8LAGF5COwuVWEIGieqkNRnIEi - +aq3ln+i9lDHpbUoqjtcxAGYaoC/AkmWwu8Zb08LPOw6yGj9Vq8HkvqYoF3PVfR44gr2g8MGBGhl - Y6NqAAXAe/SxqGJUsN22Ag9TDKWcMPxM/K5+7IqQixQy6FvqNrQ4EHwAJUxTZZH/8A9q0r7SWYtv - 65OSbkaIaO7ZNxzqvCP5f+Ut05BX7xpVlJ2JMxZFGZCy+s0/0uinhtPbUsL3XqFhYVVFFGlfMpSX - KZMNIo7I4e+NzMpm90gHQpfbCoR2zafhxgADsEaHi6LNrm+1kHbL/acPKctAXbFeWFrUbjceBYH7 - kVdEVMP5B2ycHD8ER3HRXAOD/UDHb0Udn7zHNXojsNFQ30A5PD15IbdyL10eGm5LaFndkxcQRonm - 7ALRJXXV6veXtE2glXCMmbtzIBycZpxipEG6T0046uBZs9XhQ27UoQ88d5ar0MsgoZkTK4WKQlUv - Sz78qafEIhiuqxSNT6NErjBmgxFCcMvu1OP5XgCMsSBYCIVB2VmbrFVv7mpH0apqc9doMmveYsAd - L20u7ejj82IipaNxJNvTcwuXpbWt5woSIgY/icD1v8ms7ugDbPxHgUpqDOUhC6PBtTq/so2bDxEA - peMxY5zLQgFxKFJW4pOa1104hg1TdZyClxU629JAAfXer+CmTbev26iQ375glBw+rNyWA9J+iX02 - nu/JwYp6Z/VLK8FY/5WWZicqRnG/4G96w6zHwkB5zD7rF44utw== - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=5-indecorous_creamery-reply.gpg - Content-Length: - - '1120' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:14 GMT - Etag: - - sha256:8ea8d0a16663cc9b7d4f2e196ecd9d675ffef7f0f9d6b51294cfbba8ec99eb33 - Expires: - - Thu, 20 Jan 2022 11:11:14 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:57 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Length: - - '0' - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: DELETE - uri: http://localhost:8081/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa - response: - body: - string: "{\n \"message\": \"Source and submissions deleted\"\n}\n" - headers: - Content-Length: - - '50' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:14 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/replies/5f5707b7-ee1d-410f-94be-1ba8c1929264/download - response: - body: - string: !!binary | - hQIMAxGWEiPHDepYAQ//XWIBkXv/uh9NDRr86nlqZ2gJGssV96HBp10HVUbyyyEVcQkZ/evEOizB - 0gFUBwqBwuYAazPNgfgEVywXbAERoFR9Pul4AjVCkHqbrPOl62BSsKpLSAQIV7YP6AlJPiO3Pm0R - VeENWPAjmotBHfpjgVwiCkQeSyF8lCAveo7707ppJT2hCpxjJQhtt1WIyOQSE7dAaAnywUWbBkoB - HldRJiKQa1O8CsNm8ELPQaczYR41LZpPHZ+h1xLR15iGnXq630ZjDagxok3+aXqI20MemxYOvIc9 - nqxQLduSWS0HykifTX7wYcCGj0PCFqSSngNUaQTAjSQPOQjUurWV4T2/aT2ixT9waPaHut8jpQ6p - Lzc0Pe/C0+yB6YBJJxINovWHzGL0N7ZWuPVmkWgPWcOCPu5Cc3pn+cv5fuqoFuJs1/G1t6eIBfqI - BMw3FPbq1sa6QUPY6RDqpRE8+48cHpVHBHKl2wc1uL9WVUtZdFKAOz2bLu7CAnD1VmZvpszgq12/ - j5m2UwINjo4N78UbjClCMgbyzji2hM9q2B7qkTf5JFZtg3YbhNKgiJxDpTcYdMG92BQS3vYjxHiR - FzxGwbDuQofyqIhIVhlK/42NZUns3W6Sm+fkl03fR72xtBdGCdC6tGJn7lrys8B8JG/Dr3LsBqnr - A+KqQNu3Xr2ERHqrie+FAgwDw+fEwKIgGyoBD/4m3ypz6E9TqX/mm4Syc+KOtfb1XXWGlrI+YtxW - cZHPI+9iCA2XamMXFdYDYueb0CGB0bP5l1THXkYsN+kvuVzcdXZ2hY1U8tMhvU/UNirdau3Is2vJ - uOQ1cqvJHTkEXEZdTzZG66Q6ZjtQjr8OMH4XugC8TKIR0gq/xmxk+49fq3FT09d+bccvFJQil5SF - +OKqJQGVhKaUd3bF/ITS20psYNcR36QK/QDrCM1dp2s85wWe8j8cnVPscuJ0lbX0qey5tMUf74Yn - cT8qNeKhh+Z/6oOjBB+UtcN/c6okMAKbX0IoQjCskE/D6ldscXkYTx4wVp3CyzZMGwyh8sjDBPp2 - ilsccaHhybJkFx+qwx/R8AoLc9za7qlfU6BYvasGeY0LmU9DCsS+fMQjL/34rkq248h4mxee1rap - v9vipuGDkd8EJMZPkR6PDL8iIHW13xqDlTEAkhuD0fsFVxGxdXgUdvNrPHb3/X+c+BDCdP1OFO7S - 0SQOO7NijD9O3NhNuKBkW3FnCYHb6sbJ5XRsD6h4LbGe6KwH97xULC4jRVSIHssTl+Nozcv1Xml1 - 4AJbGtcpna3Fc3Arjjop8UNoDntuDfXEuRulX+Hckib/IrIGTqgoEHYCEd/RMhY0ZE2hT/7iQBaT - FMuOpyvlV+Mb6zjynz3qy63WKV/cIAT3LwrWOdJCAelNp8jPH79glm+vZoeaZwjztzVucJRxKxtN - CuvLf+ziRI9v1FiL5GT5LAPpr3jtZ+qi9j9rKKAtPKfINXiS/B7M - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=6-indecorous_creamery-reply.gpg - Content-Length: - - '1122' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:14 GMT - Etag: - - sha256:1342def77aa79e3babeb0b709cf3dce39e69a8e1e04ec0c6a41c8aca6a979600 - Expires: - - Thu, 20 Jan 2022 11:11:14 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:57 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/replies/9bb8030a-8561-4a03-85dc-e921bd6a891c/download - response: - body: - string: !!binary | - hQIMA8XplUsUkq4fAQ//dI3ZLYYvp5nURcYqnL+N6qkdzdZ8SV8zxGd6wI7Oc0pUQy6Ri/Ap4gVy - 0fQGy+gA6QI599dDmRA5IxNV2GJ7D1KGkwCw9149ZGx3s1Qk9xDLN1+2xr6wbC8WnO7aMb3XPnzK - hEOpX+GIxK+PShiwR0TedX/M1ZybM2YNxuJn14/yO3tbr9nhBSujuQkSitQ7xdccdYiO3laJNjD1 - h1/aSUPz5yz77as0ctRoSwjl1+JY9O0RhclEKF8T7lIBms+uZwZ9b5yfQIlaMHd7iGT4HdIUMPjn - QWn2JmJ51BEa5G1Gpu6wEu5xT3fl6Z3Il3T3ARY96z9Ps2sCQg5FrTJ7U+RRj7yt2Xw1PF13DNpm - Sd2y6Qhpu3lFkM8cIzI+4O5mYL9Qe+9vy6B83vCtDKUZ9jqcZuGa5HD6f4Gzcu0FW1WAbCT02MAY - YTM8p/tyAoEIKgKcQxFmEhMFbaPOQ20TRXKb+x5sJGh1i5M4CmMQsGvczZrh13Zm5QIw9cIqc4de - uh4WrMsSHlGpdR+glbzRq7kCoofi3QOSrsTGrnaIPqPp4M3VNNJnR47yipKLFSGMI4T6zqHSTelW - ClhS4svd0qSPVK+DWD+XJ5lHrUDIzBM7FyGEkWAQpbqHIaE2fAN9QloAkcTPSO3A3/MdnYKHFLPC - BT+m30B2N7D1S7HC5geFAgwDw+fEwKIgGyoBEADBNF5oX0O6LpdpJAYuZpoZkVbZ6ZK0uc9gTh5N - CaoJNS2gHZtwhzqfgFzZVu9hERuUFvELXaeebv8zxNSRohUtIr0uDOWA9ZFJ+IrzaSBEfns28jkX - b8GsGeJQ3FPnvdp0LtOGAsrUGj02e71lJOx8qCfVgo1d4ZKxHpCSdC9+CoZbCxPE6a4TRCiE3Khu - /DDi96t2C5jNRHCIsfgwbaBB7sLeibkiIMhiKYGMz994UmA82XAHPdkIgXUsgju1UwxKfxk84Kwe - F1hybOfkpjAJ7kH/E5l5Udy7eEk5kz1M9TWr2UHSpY48x/enEOWYoAcC7f3tBKWak3WrxOhCjPjk - /7y1vSMKCLnsVkdNAJ6DTMpjQsv5aKuk8UPMTqw5oEl7JuFKcwdztXOgtsVXbe8t0rYTLMJlDa7w - 5Q5erJ5PdkQexpccw68Xswa85GZSUCIwqywrW4v5T3oemN8ZdZWuACFLBPvv6/JeRg+wEN4lk7qk - 7Q9FnjbY8a2Wn6ydCh81gAm6XQn5s+HH5FEVrJBbVrshDXZgdFIfLer2yyVOBOi8HnzYylxBgOHH - IRRlW5zV3c8bcPsX4doyiHXg6Rq8xs0vJRghqVRJXLYzsp2KG9h8gUvvX4F6I1o3zTE9RRI7jUVQ - sg81ViU4toOfaLcKuwpXKfy8tZR37+FZqWQSy9JSAdJ2DdIiaFHAX636/MO3AYocVMKsfQHHMmES - zPxveAOVrYp9wctgh3dNe7tJqFJZgObxmyKWdeLTmC3LE0P9d73Py9yfqmlZ8ADishAQToTzkQ== - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=5-concrete_limerick-reply.gpg - Content-Length: - - '1138' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:14 GMT - Etag: - - sha256:be7131a49df1b7a26d0610a96294198e1b27d7f13c18fc7b420132e9604e878a - Expires: - - Thu, 20 Jan 2022 11:11:14 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:51 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/replies/0a82f046-581c-49ef-9b51-ce5b73e45c1a/download - response: - body: - string: !!binary | - hQIMA8XplUsUkq4fAQ/9HcK9M4c7Tks2GRPrAJgP7c3FGgz8Q/2HPBNoc73Fu1vsFUy19Zk2UfKX - 5LpKqFvMvo9T+HZPscKkoYpru68WahEAyIvdWRXl1OP072usBa/pOel4MdsX0l+ShrjK5H860zp3 - shnbNAhmpeEJ2TNQmDNj6UQsJWTS6hMoxAWIxBbuScqUk5T9oNEL7BSxZQnBfsMt50EPf3F4Fcn4 - aFRwWZtQZYlJjTodr1QiPykSaN88+ipqB2WatT+zxwBDVhjZTDWLZeprizvV+Ezxk4HwkGVm4C3C - lGquJCjAKt6t392zDVd1jEy83ctiu9DFZ/RBuVt6ath47JpXXKYu9Pm+hwYOZ5jOlE1C6z+B4xWd - sEDpocvIUxt+8VZx7DGACGRzHbJ5NapObt2eX6sQgxyMOwmg+bYqo7DHfbyMdPLY4SE+mytI0/Z2 - mm3/6yOOnAEOl3+5/M7aUPH3qUy/4S63iJKQ2banBSD0yDNQ6I/0MnU31AysERrRCSdxOExq/9u0 - IqHhb0In7hX+6EM3mQSg+z0AvX/xHWcn24TeSjMv/9WMFcasm85Xb305FVFrRyeMPUDcrbwepp8G - J/pj7mldMCe+5I17pxnQ8sImFt/GZG8DqoVrR6K2s5s2DCKywizUjifHg6L1sM8gY8d80y50U6mR - Tr8WNtdIdVuANcufU26FAgwDw+fEwKIgGyoBD/9+mmWhGDd48AshmcJ2SiqkgYuYUdp10ujWVZNx - IN2o5monN2AXkTyLUH6h0f/5HtJEGkoqXzQUs/DysOIRu27QqMS4BjW3fWXfqcKlBXItYHdd+BBw - czdqXrEMxdFv4MiP8q796+keQsJizPInpyApvFz4j7n9oLyshNLU2z+QoDkhKir6q+kSoDkuySug - JS0qzkdP0zp1QF/IzmmdyOLbApIZpYCY/wJMxVrqeBijl6cwHV5O+PMw0415WRxNXZ6PzEGzMeX0 - zSgputz0Jx4f7wpRjS/jgcP66VHTAl0dAKtEY7FHPUS68/0tBhsLOYGv8AJA4evAeVPCWhj4zJH9 - dpTTJd8PDOapoQH/xBEvt6AN2WKXeDH52tl0QFdtmVDPYjbqo5zh/qctHKv0QdsDjZZXmpnTCrfq - nnLRagcPeW6YKyn8yhrP44VR6Gzt9CSN3HGPmjfy72vqnyB0rEdkYoSEZZ0hxTsZ3QMT0bZ7sDPA - XK19LW9BRzjZtlKSFGONuciDN5lR4tQntGacjMcOj/xGe65PmuL484mak/900Cx9jwrw1hdq+a9e - gpKDsc4KG9suXkiJrzEHQE+18kgRBvoMZTAbumECKOuHUgZ919F1GgV3No6XjQZ+botyN4mgSwJm - VIV18ep7w0SQF8Qb+BCo8mbS64+nXd4cQfwtktLAIwHCxqT2yTvD2UXrLQXoCIvFP8xJ6T92oCgn - sSzyBciKz7C4EQ6N9dKQSo2ZXHSRO81/LuBGhreMQnhYiV90OceTFJ+U0nFWh7smggqjZSlqflg/ - W5wcqd945LAnGlQPky0AQcOYl5cFa2cHE6FZNhs/hQL5CAIir9AosMeOz7A+msaijWWsnkfc8KAF - HIrk8/qi7WDKd3ni++4dUBP9+xWijpy6jHzD3DJgP30sXFCDAjlvz+4Qopz4wXTncY03ypkcEGjP - sGsGWkGeBwyOvdxwk02XXTWyFv6aFenv6dNoJ/Mv - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=6-concrete_limerick-reply.gpg - Content-Length: - - '1284' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:14 GMT - Etag: - - sha256:df33b47b1b077cad3b8ab00a5eecef38faf353be83387ca4ddafe193a8ee81f6 - Expires: - - Thu, 20 Jan 2022 11:11:14 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:51 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/replies/9df9083e-1ac1-4085-883d-8c9982b6ad79/download - response: - body: - string: "{\n \"error\": \"Not Found\", \n \"message\": \"The requested URL - was not found on the server. If you entered the URL manually please check - your spelling and try again.\"\n}\n" - headers: - Content-Length: - - '165' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:14 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 404 - message: NOT FOUND -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/56d6777c-fdb6-474c-9d3b-0b7b43beabfa/replies/ba38afd6-aadf-48d1-a599-bd74601105d9/download - response: - body: - string: "{\n \"error\": \"Not Found\", \n \"message\": \"The requested URL - was not found on the server. If you entered the URL manually please check - your spelling and try again.\"\n}\n" - headers: - Content-Length: - - '165' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:14 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 404 - message: NOT FOUND -- request: - body: '{"files": ["42f45442-ee20-4745-8518-c8a01bad5f46"], "messages": [], "replies": - ["9df9083e-1ac1-4085-883d-8c9982b6ad79"]}' - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Length: - - '120' - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: POST - uri: http://localhost:8081/api/v1/seen - response: - body: - string: "{\n \"error\": \"Not Found\", \n \"message\": \"file not found: 42f45442-ee20-4745-8518-c8a01bad5f46\"\n}\n" - headers: - Content-Length: - - '97' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:14 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 404 - message: NOT FOUND -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/users - response: - body: - string: "{\n \"users\": [\n {\n \"first_name\": null, \n \"last_name\": - null, \n \"username\": \"journalist\", \n \"uuid\": \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n - \ }, \n {\n \"first_name\": null, \n \"last_name\": null, \n - \ \"username\": \"dellsberg\", \n \"uuid\": \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n - \ }\n ]\n}\n" - headers: - Content-Length: - - '324' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:27 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources - response: - body: - string: "{\n \"sources\": [\n {\n \"add_star_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/add_star\", - \n \"interaction_count\": 6, \n \"is_flagged\": false, \n \"is_starred\": - false, \n \"journalist_designation\": \"concrete limerick\", \n \"key\": - {\n \"fingerprint\": \"CA8A176B4D5D3666ED88B03BC5E9954B1492AE1F\", - \n \"public\": \"-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\\nmQINBFGRfoABEACtbh8mDuBbRxk7YGntX40e41q3r6mLgGmV5p26GZi3b/fAPoWA\\nJjo/Np5uBI+Ye/MZNZBl22aGIh3iamNXpywjrro1xCFryAhdFMj4eKuarekVbsNV\\nj0K5AWH2gomzJ27f+9+rkn+R5gtvRqeMA0tVu7pQQ7gw/n/1XIJ4X0M7oRHPWNAX\\nOvAJe/60jKTAiwNdgwE2a5aOTXrtXz20Je7bBq6TtKAWa9tdB+W2JUNH5IEmnhYA\\ntWw3/GliQHphPizpa4eE1jgF3IJtNf7hPTeJ7S50XXpolfmIaLYohWDuVi4LFVGC\\n2GGzasNefQJIoQXkK2UmYhhck0T4U5zwfl5RkuftOjGvHDa4U7bSRz3rl3MCzmGc\\nlvA028aMRrYg4nBu0ryVlVjAV93n8FTKasURjsyLVBfb+Fzxu1ebbG8rakvHbAbk\\nK25ZP+mNyu2QZ0WsM6j3C7afvAJDR0Mkj0KWBjc5JHMUtqupPwpK/8eswlecx7Yx\\ngLAwqkmYvFUiKjKAbUYbaOe4YJEUj4h/nxayXE2XhptLlL8m4oopflANRsqc00+F\\npQqcznyL0a89JKBmBaT8xPPK+GOtrs0EU9mz2IhAB4HxEKuVFuwOg7AIFLO6gRN/\\nLbqJvLz1IO3yM10O7gCb8ErPxrnByBkP417YWddnx9pPw0vPgPXy2lbo6QARAQAB\\ntHVTb3VyY2UgS2V5IDxPM1hKVUg2TkNaWEEzSlpOUlpSRlM2RlRaQURTUzNNVk5F\\nVFlNU0lRWjVZSDNUTDc2WFk3VjNQRTZSSkVINDRKMjZXM1pZMlVJNU9KMk00V0VG\\nWE1aRVdJWlBHS0NKN0VLTVRCQjJBPT6JAk4EEwEKADgWIQTKihdrTV02Zu2IsDvF\\n6ZVLFJKuHwUCUZF+gAIbLwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRDF6ZVL\\nFJKuH04ID/9Xl2jbyBsu+JHS3fsMDSZE0L39HhqbRKqrUxq5U9vb3aWU3Imf3Tu3\\nez8Sp/aThXOJKuC9QeJ2gCIe9+V+OGVYvUl67P3xxKzIUmlLlk5cbosC9m/J4MMZ\\ndmSok8XBgOWYWuNbcCNiW0msfDijJH1diH6tDc9UEzcTvTbWHqbl3S27uwVced3O\\n8OAY0MGcB6Tw1yRBbv7fJ4nWKeu3kmzrepRQYh9cEMEf+pDE0RUkoORiQI5vmtzL\\nv454PfNGGuGijMQm64tYqe33fwMR0marbLyYXTSMlzEDF5AxeaKjDVI4kEe6eUT4\\n8kLsvRl2nPX1gbrBSkHSZ21/oMkhdlGhPyb4xKcqCVkzpQJpCsATmAkjtp/IHJib\\n2mu6TzhAIvANP5jqiGE128lZpPBILq3PIrhXqVDyLWpl6xTSHz7rhxVXtDHJZoIz\\n4QJM7Dl9V0s/UQ5hJdmx5L0aEP+7b46+3kvgbPvItaRiF11L7fRQwXMNoI8bm47T\\nbfW5nJK8p6O5VssHtFYqL9rKYBDdk6JYsiZ8xvTrqTRMK1xJEsuF3Tuv73JmMQtF\\n7wQq8rZg0cbINpJuOBRsvEAo6ATJBq+HOCAuqvhJ3Kx9lixLnURP4dybKJoTdWJP\\nSDgLwly7bulTF+fHQSlD9cypaLiw4cyzFubhw4OWEJYMAsYcbfBqYA==\\n=i+xf\\n-----END - PGP PUBLIC KEY BLOCK-----\\n\", \n \"type\": \"PGP\"\n }, \n \"last_updated\": - \"2022-01-19T23:08:51.571224Z\", \n \"number_of_documents\": 2, \n \"number_of_messages\": - 2, \n \"remove_star_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/remove_star\", - \n \"replies_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/replies\", - \n \"submissions_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions\", - \n \"url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"uuid\": \"ae59153b-0871-411a-a72a-0f4c41a76ee0\"\n }, \n {\n - \ \"add_star_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/add_star\", - \n \"interaction_count\": 6, \n \"is_flagged\": false, \n \"is_starred\": - false, \n \"journalist_designation\": \"indecorous creamery\", \n \"key\": - {\n \"fingerprint\": \"04DD6C14755616B9F944F87311961223C70DEA58\", - \n \"public\": \"-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\\nmQINBFGRfoABEADEMD/A2IVlAmhB3Vu3jDlG3UFli/e20GXvfeW6S0PFEuvE9Po9\\nCjI43sFdMVvRUvtaIP5PE1zU4OuN1gi6jpKp5puulnddV6jP0GXqK+hqVXjiaf58\\nhUkuvpK2CaHf/5DvGdSW2IZLB9oP/UtWYTBUm7dER2Fc+rMY13fUMEsGKyJZ9wB3\\ny4CrJpMw7TNTefVx6vrlbCVEB4nksod+A7wteLILbeGj26D1A94vH1V4iLdOObW3\\npbTX4Yra1CpxclEsHyaS7tZ+4bQOmh0OdVG7ZW4MZPYp+1BIqt+e48042Rq1jIHu\\nHVApvHynPDt2tD/KiymDM3Bt69Dy9rHrWEFlWAS+Fpgo7qBQ9QF2fHWzpHQyhcTB\\nM3zQ2LraeOrBWgzjgCRIei+sga6w9Tjk8fMZKLl7HPkjRZxOFU4GJLjkxf3Lw1Av\\nCo3kQijDzj0nN/qyebcD2/v6vz5/5D8iS85fJdgLwds7ajXXgk9/M11Bkze1RT+2\\nYCmsUW999wF+AZmeR6ZFdUfcOpJE/99zs6GIRIo+ikPWiMcs4/7jAlrierrAtuhH\\nl6luFRIz6utBFWIleZosxnx3ZqRAv1DUdig3BnIliD3Y53y0cHbFFLOX428ZGKCp\\nJ9Of22l5XfMlT6B8NCJgRcQc77beedl+1XcQP64X+FgddottileDhsiRNQARAQAB\\ntHVTb3VyY2UgS2V5IDxHSlFBVTRBVUlOQVNBRk81R1I3N0NMNUpDWFRMV0FXWjJU\\nV1BKSExDSTRJWFpNRVFKWVlIRFVUWUFNWjJOVDJLUDdPN09GSlRRSkdTSFJJT1dP\\nM05aS0VGRU01QklHTkNWVkFFT0xRPT6JAk4EEwEKADgWIQQE3WwUdVYWuflE+HMR\\nlhIjxw3qWAUCUZF+gAIbLwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRARlhIj\\nxw3qWEDyEACKKS0y7ApY7CMGuuU6BltrUyc7A5UcCe6vnCREX4662qkHgaDLmIpa\\nb5t+hvtOicEwegoFsBAnjnG+Vs+AU1DDzXREojZ0T39Hyq0PYS7HbDWJRUSfl//Z\\na566rtbdzv1GEc7hMAEi9pKplR3uEQlQAp1G6W1Yzf5WuwmdWMOactzbENJTnbc1\\nSBe/oKbH56UEMX7KLr5MODQ6IM+VCqRI/k6Px065q8scAeEQERwUFdy33BBzk+g7\\n/uYPC74NnfISP6Tj94oFEySs1HC2hIaZlUQor3ZJOzvZ3Vm8hix7JdjBVdqdHFmx\\n5+Ft211Va6v1dKCUW73GPvYkv0bt4CeAV9fhyQOSMSENTiNVVh8L2+dCXVQXhFUw\\n3Hmu/tOj+r2B8+vWWHuhbFjgeAiXFkHFDT1a3xZ98n5g5SNwoiBJDuyWjPgr0vG3\\n/+1wgTovRVbt62H1VgRsP49wMS9EBz1DV1q60GcWD40FNfkJx7W1T0RtUgpKp3hH\\nw06RJFAzeMJtXz89mFpIQfkVwBflne5HDQywIT8o0TnxAh06Q4ROqhFydDSB0HTv\\n6NJVRhiSiwGmYiZi4DVwv7exttrfv6h1TX99MjR1e3kjki/IjeI/pW42GgFUZVN5\\nWRzx2yiSIfz1rhBqnRAtZWConlmG2X3LRbUFtz1LHsbC8UqKdtlB1g==\\n=oWMO\\n-----END - PGP PUBLIC KEY BLOCK-----\\n\", \n \"type\": \"PGP\"\n }, \n \"last_updated\": - \"2022-01-19T23:08:57.846667Z\", \n \"number_of_documents\": 2, \n \"number_of_messages\": - 2, \n \"remove_star_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/remove_star\", - \n \"replies_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/replies\", - \n \"submissions_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions\", - \n \"url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"uuid\": \"55fb95c1-cff3-430a-8c05-125c67c81a6a\"\n }, \n {\n - \ \"add_star_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/add_star\", - \n \"interaction_count\": 6, \n \"is_flagged\": false, \n \"is_starred\": - false, \n \"journalist_designation\": \"conjunctive lavage\", \n \"key\": - {\n \"fingerprint\": \"F71969D1705E2E3E374B95992DA6D8DCEE36946B\", - \n \"public\": \"-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\\nmQINBFGRfoABEADcaB1fww19PLIREowYKfNZiVoWpLYxRnw1U/Iz4JbnEJ7TuIlm\\n2Q46Hr9kR7zQVb5okjn40whN0JA3lJcfPZdjfxiCt8VYI7vacUxVZgXWJCR83vO4\\nNSD1YnZD5KXi0B6PGKIhry1Hqc+hzmMAFYGGdi4h5EKxinNmKTO+E3Zupeydm0KK\\nCBwXroROAs/5+s63oj5+nuqlPCTcEL3SGjH8zXIw+TN0mBhQhGlyqofIW/JEaviP\\n+frUL6WPa3AoUBE+TAF1rmXr30phZU271zfAYhe0B81gtrUTSg49uUYQuCf1xu92\\ngbuOmcYTQvdzgGDp8cNWL5cmQCdvoGTGH5PYodqMGcRfWqB1dl37RCsqDcCzssdv\\nJiUe8qC88n0tQl/gJOgniEhKEok5EiaGuuLz9j7waGB1aBgHLPsibDGQVyYn9ZYD\\na3E9cL0BHzsWJc9i1hFE2cmTXzmJ7rTXyvHSvidT6s2cljuih1Q6e5qNOcJPAuv9\\nY2xuZHn+rTaJSLM30X7PngrAP2jfepraz7zy2lE4Uex9dLQNPMcYhjPc9SwKjk8g\\njDkhCGW6daRCpzNUR/ydYGlfN00L6MPo0S3XG/x88f+OwqgfSpgrfSijqDTLxbo1\\nO4rTW+KSiVy2P9DfuLhZv+HcNiinY0EP3qbuuXKk7VSMeCir+HgeDce+pwARAQAB\\ntHVTb3VyY2UgS2V5IDxTV1pWS0hOTlBLQkIzVTJDRjNBMjRIUkJZRlRNNkNDU1U3\\nM05XQlhNTkw2NVFRWktEM1gzRllNTFVDVlBKRlhCRUJWRVkyQklKWVJLUUQ2NUFT\\nS1IzQTNaTVhaMkFOTkI2Sk1CVEJJPT6JAk4EEwEKADgWIQT3GWnRcF4uPjdLlZkt\\nptjc7jaUawUCUZF+gAIbLwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRAtptjc\\n7jaUawViD/9O2J9EsxOmaSB3XI9q0EyLvOZPh+r9TeOGA4kqQlOH3PeMP1lxQ7v1\\n3LR7OCjM2pBNHww7rRkYNoJX4dA/UjZ1UcerIAbxa2Z4v7X69akKItw889UCW6Go\\ncUtco2XqkjaThsV/io19+6qFicrWAumpFtH2Dt8iVsHzOYWpijPK70AxJqODg+nK\\nv4k/+zqAePbLOCCCuvnhBduJCEd3dA0G7ow0H/AzgpPKOEswbYK6JJYX8Gsq9F3n\\ne+PkBJ3Op4/qUELYQYEBbF2qy+XPfhOZsJ4v/HDb+eutZNmATtpGZGNJznyLFoZX\\nbNI/U2XIlQYBDeYTOVbNPPVwoVucoXG1iGsp+2ZFvLgP4XGRxdH9oyiia9FC+id1\\nwCtS6dRWRKv1VJwVetGBncAdwmugCkQoJ/gGwcTkJLhOVyoZZruTR8aLOE+ArTUg\\nfgKBVpeT9he8ELDZFrPtAnDTpMS+RrVsF8Y1sih7O8VCxsxGRegKlQcxgPp7/MdG\\nwFOlulTqCSu+fZfkid4rvnRGcPRp1DQohwXiK/UpDIRYTPERHQTEm2fK29FzmruI\\nr4zotTaeHhztY5jrqZqzkMy6/teHE5CGq5mKQsXzQFjb5hKEYg4TwAazPRtH3WOo\\nkZ5ISlxKvOdf8jA9hWKFrREtk9t9blD0IA3ffzfO5aad+aZjnqsgyw==\\n=ccYc\\n-----END - PGP PUBLIC KEY BLOCK-----\\n\", \n \"type\": \"PGP\"\n }, \n \"last_updated\": - \"2022-01-19T23:09:00.294006Z\", \n \"number_of_documents\": 2, \n \"number_of_messages\": - 2, \n \"remove_star_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/remove_star\", - \n \"replies_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/replies\", - \n \"submissions_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions\", - \n \"url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"uuid\": \"50c5fa95-eb69-49b6-8599-62b12cff7d7d\"\n }, \n {\n - \ \"add_star_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/add_star\", - \n \"interaction_count\": 7, \n \"is_flagged\": false, \n \"is_starred\": - false, \n \"journalist_designation\": \"sixty-nine alliance\", \n \"key\": - {\n \"fingerprint\": \"7034A99B359CA2DD3F57E251437B6C3C6984302F\", - \n \"public\": \"-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\\nmQINBFGRfoABEAC8d/LgDtvyeg/SNsUcUPRY7JZGFbE3peoduYiqd29LW/BXoInn\\ntRV3Ks5H8QLH3/qS/zWwiE4x2yE8cOykWj/lPMlFCDYdWK4f55eS1LcxN+WtLiaL\\ndDQG84KICZznbqTxlvdizLwCvch9Y19dPszPuwrBJ2KbOsngPfHDARs2aU++J1d1\\n7MjIpBLJHTlYKRdutANtxEKCq+KX9/K8GnjZYLhmmecaVr6OoSp3Nq6zlvJe7qPb\\nc1IUJhA1oDyNVBAPs5ROKkM6qhDJmI9OpKoGVGWG7u3kDQ3Oo59wBoC65xTZNFy1\\nGKcQbCcegKsnxdchBO9nMK3wh8H6JUkpdXPrurysHqQ6JIAar0rXIlOvg8kD6yNU\\n7bYK6xetBzkYBGgz7vbgYq+k2ur3nQLvJmBnPVqY/7bjSGDIfbkJWOudD2LaqQUc\\nIUeBpTlOsqfVhXwfen+ynntPdSQU14ILmQAztFzZor2leNWAR6pYG6ZI3vEzAX3l\\nWPzmS7L13VC1w11IG0wdKuzhx1jHGJ32JrNyL4LoJ1O++8GWlJS0+ZC85gwIaFQC\\nLB+sGw4PruxLUGFe2ZLYWgYnN3Iw5JBPxfc+Kxrp1xhHCZNdC1B1ajtkOwvdZbIU\\nOP9Cp5MRt5AeGBZ9ujIMsAxOZrPeN574ewqnY+z431eC6rNFzdmlY1Av8wARAQAB\\ntHVTb3VyY2UgS2V5IDwzSjI1UlA3NlZUWUwzVktMV1haTENOUFI1WUZMQzJQMk9Q\\nRFRETE9IVVFQQkkzN0RZWE1CWkpORFRVSkxSWjNDUlc1RkdXVEJNSDY0UTNBN1BZ\\nTk9KTjY0T09YSFpRRE5STDNRWEVJPT6JAk4EEwEKADgWIQRwNKmbNZyi3T9X4lFD\\ne2w8aYQwLwUCUZF+gAIbLwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRBDe2w8\\naYQwL7osD/9nj9I/89AR2p+MDw+RqGjNrEMnIyCC1+IneGC5MJXLYb/9oz9JRMrb\\n/+Gk+MhPjkgHVbI9BzByIzNh0stYF1T17rJDIyehjfbejYQKFwJd1+QHCfSgLIQQ\\nNOtKKr9iX5fUdPzlLzkdaTRGMidUTqWuY77wgmZoKN1a1Q801NXjIkY3QJ5GpjSf\\ncdvgu77k7y/0juUu0eTeNpd1TXs/GBitETnfDEKcVUkk8x+OwvSFE7VrWJCNAH/x\\nOAQUeT9S7CczoUeFWCII880xFcpdynt+ogYyxVh22RV13HJ/HJlmUA+9cpQ6ntAW\\nXdhKS814mJjqfTk5j2ZzLwKekqQgUSjCB7ucbEPhaHdQHShfuNQg9EhtP2Qy+Ptg\\ntGFMF4f+s9anFobioeYnS9S3JuR73UHD6XOz4GDgGx/3kdlxwRfjOqnRWzC3oNmU\\nVmT2caEmXnjEqL3FP1wVOEcciBqOAgT0QsMB06eOHL+cJxMOE6j/Wo4Y2loF0+Bq\\nR0KMqbg0lpSyLHjTmOo15DgzohSALI44niM1SaVGGlzOawb5zOd8ownvfwcut1wG\\n0UxhwbyoiHblTySzzjhekJQGMGQOyRUIfbjbNtHKeVFVEosM5dUhXWRA+8n1uhc+\\npqdAhXSd9yEIjy8dIc7USlTTqEEOYYXetEWYJP6tolKuggSiiUB49A==\\n=9Hjj\\n-----END - PGP PUBLIC KEY BLOCK-----\\n\", \n \"type\": \"PGP\"\n }, \n \"last_updated\": - \"2022-01-19T23:09:01.659060Z\", \n \"number_of_documents\": 2, \n \"number_of_messages\": - 2, \n \"remove_star_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/remove_star\", - \n \"replies_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies\", - \n \"submissions_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions\", - \n \"url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"uuid\": \"92b1914a-1b1c-4674-baad-1fb662aed682\"\n }\n ]\n}\n" - headers: - Content-Length: - - '10778' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:27 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/submissions - response: - body: - string: "{\n \"submissions\": [\n {\n \"download_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/48bcb4a3-6f23-479e-a718-e0b93fd4b9c1/download\", - \n \"filename\": \"1-concrete_limerick-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 611, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"submission_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/48bcb4a3-6f23-479e-a718-e0b93fd4b9c1\", - \n \"uuid\": \"48bcb4a3-6f23-479e-a718-e0b93fd4b9c1\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/d8db9ba7-4789-41c8-9f7b-3761a367816c/download\", - \n \"filename\": \"2-concrete_limerick-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 757, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"submission_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/d8db9ba7-4789-41c8-9f7b-3761a367816c\", - \n \"uuid\": \"d8db9ba7-4789-41c8-9f7b-3761a367816c\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/648932a9-7e82-4fde-a65a-fee812b50ec0/download\", - \n \"filename\": \"3-concrete_limerick-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"submission_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/648932a9-7e82-4fde-a65a-fee812b50ec0\", - \n \"uuid\": \"648932a9-7e82-4fde-a65a-fee812b50ec0\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/e0565187-d9ea-494b-8ea0-173befacb1f3/download\", - \n \"filename\": \"4-concrete_limerick-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"submission_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/e0565187-d9ea-494b-8ea0-173befacb1f3\", - \n \"uuid\": \"e0565187-d9ea-494b-8ea0-173befacb1f3\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/ecc07e49-be88-40d5-8e99-bfb3b3812668/download\", - \n \"filename\": \"1-indecorous_creamery-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 593, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"submission_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/ecc07e49-be88-40d5-8e99-bfb3b3812668\", - \n \"uuid\": \"ecc07e49-be88-40d5-8e99-bfb3b3812668\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/c60627e5-dfc6-42dc-8874-b290ef09a2d9/download\", - \n \"filename\": \"2-indecorous_creamery-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [], \n \"size\": 595, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"submission_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/c60627e5-dfc6-42dc-8874-b290ef09a2d9\", - \n \"uuid\": \"c60627e5-dfc6-42dc-8874-b290ef09a2d9\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/0e734035-3193-4c94-a86a-41d04332d8c0/download\", - \n \"filename\": \"3-indecorous_creamery-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"submission_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/0e734035-3193-4c94-a86a-41d04332d8c0\", - \n \"uuid\": \"0e734035-3193-4c94-a86a-41d04332d8c0\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/93d72061-a8f5-4166-9a7a-3beeea4989e2/download\", - \n \"filename\": \"4-indecorous_creamery-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"submission_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/93d72061-a8f5-4166-9a7a-3beeea4989e2\", - \n \"uuid\": \"93d72061-a8f5-4166-9a7a-3beeea4989e2\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/f2fc98d1-8acb-405f-a4c3-c93bf23febba/download\", - \n \"filename\": \"1-conjunctive_lavage-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 638, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"submission_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/f2fc98d1-8acb-405f-a4c3-c93bf23febba\", - \n \"uuid\": \"f2fc98d1-8acb-405f-a4c3-c93bf23febba\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/4abcd4b4-3922-4ae0-ad97-9186f51e172c/download\", - \n \"filename\": \"2-conjunctive_lavage-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 667, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"submission_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/4abcd4b4-3922-4ae0-ad97-9186f51e172c\", - \n \"uuid\": \"4abcd4b4-3922-4ae0-ad97-9186f51e172c\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/2281fccc-4cae-4228-a837-e6f3a3e1e6d2/download\", - \n \"filename\": \"3-conjunctive_lavage-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n - \ ], \n \"size\": 661, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"submission_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/2281fccc-4cae-4228-a837-e6f3a3e1e6d2\", - \n \"uuid\": \"2281fccc-4cae-4228-a837-e6f3a3e1e6d2\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/098a7d90-0ae4-47cf-a7a2-2afc00094a3b/download\", - \n \"filename\": \"4-conjunctive_lavage-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"submission_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/098a7d90-0ae4-47cf-a7a2-2afc00094a3b\", - \n \"uuid\": \"098a7d90-0ae4-47cf-a7a2-2afc00094a3b\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/546e7e6b-ac50-4ba7-b738-82f0d261feee/download\", - \n \"filename\": \"1-sixty-nine_alliance-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 591, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"submission_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/546e7e6b-ac50-4ba7-b738-82f0d261feee\", - \n \"uuid\": \"546e7e6b-ac50-4ba7-b738-82f0d261feee\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/987ef070-4e9e-43e0-98e0-2c623607aae1/download\", - \n \"filename\": \"2-sixty-nine_alliance-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 591, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"submission_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/987ef070-4e9e-43e0-98e0-2c623607aae1\", - \n \"uuid\": \"987ef070-4e9e-43e0-98e0-2c623607aae1\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/2df5a904-e89a-48f9-9e33-5b9759317f1b/download\", - \n \"filename\": \"3-sixty-nine_alliance-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"submission_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/2df5a904-e89a-48f9-9e33-5b9759317f1b\", - \n \"uuid\": \"2df5a904-e89a-48f9-9e33-5b9759317f1b\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/03d1920d-d4d8-4580-9c42-6333c812383a/download\", - \n \"filename\": \"4-sixty-nine_alliance-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"submission_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/03d1920d-d4d8-4580-9c42-6333c812383a\", - \n \"uuid\": \"03d1920d-d4d8-4580-9c42-6333c812383a\"\n }\n ]\n}\n" - headers: - Content-Length: - - '10192' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:27 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg3MiwiZXhwIjoxNjQyNjYyNjcyfQ.eyJpZCI6MX0.JsSnOebmmONZBQbDCorvZyvh-ieMX6D8ekEQ7N0O1yE - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/replies - response: - body: - string: "{\n \"replies\": [\n {\n \"filename\": \"5-concrete_limerick-reply.gpg\", - \n \"is_deleted_by_source\": false, \n \"journalist_first_name\": - null, \n \"journalist_last_name\": null, \n \"journalist_username\": - \"dellsberg\", \n \"journalist_uuid\": \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", - \n \"reply_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/replies/9bb8030a-8561-4a03-85dc-e921bd6a891c\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 1138, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"uuid\": \"9bb8030a-8561-4a03-85dc-e921bd6a891c\"\n }, \n {\n - \ \"filename\": \"6-concrete_limerick-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": \"\", \n \"journalist_last_name\": - \"\", \n \"journalist_username\": \"deleted\", \n \"journalist_uuid\": - \"deleted\", \n \"reply_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/replies/0a82f046-581c-49ef-9b51-ce5b73e45c1a\", - \n \"seen_by\": [], \n \"size\": 1284, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"uuid\": \"0a82f046-581c-49ef-9b51-ce5b73e45c1a\"\n }, \n {\n - \ \"filename\": \"5-indecorous_creamery-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": \"\", \n \"journalist_last_name\": - \"\", \n \"journalist_username\": \"deleted\", \n \"journalist_uuid\": - \"deleted\", \n \"reply_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/replies/1c2ff7fa-252a-426a-83e9-5840cf657739\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n - \ ], \n \"size\": 1120, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"uuid\": \"1c2ff7fa-252a-426a-83e9-5840cf657739\"\n }, \n {\n - \ \"filename\": \"6-indecorous_creamery-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"dellsberg\", \n \"journalist_uuid\": - \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"reply_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/replies/5f5707b7-ee1d-410f-94be-1ba8c1929264\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 1122, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"uuid\": \"5f5707b7-ee1d-410f-94be-1ba8c1929264\"\n }, \n {\n - \ \"filename\": \"5-conjunctive_lavage-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"dellsberg\", \n \"journalist_uuid\": - \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"reply_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/replies/158dfd73-3cb3-4a6e-85b3-f37ae54e0802\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 1165, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"uuid\": \"158dfd73-3cb3-4a6e-85b3-f37ae54e0802\"\n }, \n {\n - \ \"filename\": \"6-conjunctive_lavage-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": \"\", \n \"journalist_last_name\": - \"\", \n \"journalist_username\": \"deleted\", \n \"journalist_uuid\": - \"deleted\", \n \"reply_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/replies/24fbb6b4-504c-4fa7-9971-e6f2d1447a48\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n - \ ], \n \"size\": 1194, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"uuid\": \"24fbb6b4-504c-4fa7-9971-e6f2d1447a48\"\n }, \n {\n - \ \"filename\": \"5-sixty-nine_alliance-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"dellsberg\", \n \"journalist_uuid\": - \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"reply_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies/4dad63f1-dc12-4162-9c59-065c88b2a8b4\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 1118, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"uuid\": \"4dad63f1-dc12-4162-9c59-065c88b2a8b4\"\n }, \n {\n - \ \"filename\": \"6-sixty-nine_alliance-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"dellsberg\", \n \"journalist_uuid\": - \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"reply_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies/d5b658be-aabd-4d7b-89c1-51de7fa246a0\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 1118, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"uuid\": \"d5b658be-aabd-4d7b-89c1-51de7fa246a0\"\n }, \n {\n - \ \"filename\": \"7-sixty-nine_alliance-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"journalist\", \n \"journalist_uuid\": - \"a9f8835b-52a6-4845-b428-61cc10561a0b\", \n \"reply_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies/f774fd7f-55ad-45a6-9a92-05053f9628bf\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n - \ ], \n \"size\": 1605, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"uuid\": \"f774fd7f-55ad-45a6-9a92-05053f9628bf\"\n }\n ]\n}\n" - headers: - Content-Length: - - '5844' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:27 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -version: 1 diff --git a/client/tests/functional/cassettes/test_download_file.yaml b/client/tests/functional/cassettes/test_download_file.yaml deleted file mode 100644 index a8e51f4da..000000000 --- a/client/tests/functional/cassettes/test_download_file.yaml +++ /dev/null @@ -1,1472 +0,0 @@ -interactions: -- request: - body: '{"username": "journalist", "passphrase": "correct horse battery staple - profanity oil chewy", "one_time_code": "123456"}' - headers: - Accept: - - '*/*' - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '119' - User-Agent: - - python-requests/2.26.0 - method: POST - uri: http://localhost:8081/api/v1/token - response: - body: - string: "{\n \"expiration\": \"2022-01-20T07:11:29.699470Z\", \n \"journalist_first_name\": - null, \n \"journalist_last_name\": null, \n \"journalist_uuid\": \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"token\": \"eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ\"\n}\n" - headers: - Content-Length: - - '317' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:29 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/users - response: - body: - string: "{\n \"users\": [\n {\n \"first_name\": null, \n \"last_name\": - null, \n \"username\": \"journalist\", \n \"uuid\": \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n - \ }, \n {\n \"first_name\": null, \n \"last_name\": null, \n - \ \"username\": \"dellsberg\", \n \"uuid\": \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n - \ }\n ]\n}\n" - headers: - Content-Length: - - '324' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:29 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources - response: - body: - string: "{\n \"sources\": [\n {\n \"add_star_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/add_star\", - \n \"interaction_count\": 6, \n \"is_flagged\": false, \n \"is_starred\": - false, \n \"journalist_designation\": \"concrete limerick\", \n \"key\": - {\n \"fingerprint\": \"CA8A176B4D5D3666ED88B03BC5E9954B1492AE1F\", - \n \"public\": \"-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\\nmQINBFGRfoABEACtbh8mDuBbRxk7YGntX40e41q3r6mLgGmV5p26GZi3b/fAPoWA\\nJjo/Np5uBI+Ye/MZNZBl22aGIh3iamNXpywjrro1xCFryAhdFMj4eKuarekVbsNV\\nj0K5AWH2gomzJ27f+9+rkn+R5gtvRqeMA0tVu7pQQ7gw/n/1XIJ4X0M7oRHPWNAX\\nOvAJe/60jKTAiwNdgwE2a5aOTXrtXz20Je7bBq6TtKAWa9tdB+W2JUNH5IEmnhYA\\ntWw3/GliQHphPizpa4eE1jgF3IJtNf7hPTeJ7S50XXpolfmIaLYohWDuVi4LFVGC\\n2GGzasNefQJIoQXkK2UmYhhck0T4U5zwfl5RkuftOjGvHDa4U7bSRz3rl3MCzmGc\\nlvA028aMRrYg4nBu0ryVlVjAV93n8FTKasURjsyLVBfb+Fzxu1ebbG8rakvHbAbk\\nK25ZP+mNyu2QZ0WsM6j3C7afvAJDR0Mkj0KWBjc5JHMUtqupPwpK/8eswlecx7Yx\\ngLAwqkmYvFUiKjKAbUYbaOe4YJEUj4h/nxayXE2XhptLlL8m4oopflANRsqc00+F\\npQqcznyL0a89JKBmBaT8xPPK+GOtrs0EU9mz2IhAB4HxEKuVFuwOg7AIFLO6gRN/\\nLbqJvLz1IO3yM10O7gCb8ErPxrnByBkP417YWddnx9pPw0vPgPXy2lbo6QARAQAB\\ntHVTb3VyY2UgS2V5IDxPM1hKVUg2TkNaWEEzSlpOUlpSRlM2RlRaQURTUzNNVk5F\\nVFlNU0lRWjVZSDNUTDc2WFk3VjNQRTZSSkVINDRKMjZXM1pZMlVJNU9KMk00V0VG\\nWE1aRVdJWlBHS0NKN0VLTVRCQjJBPT6JAk4EEwEKADgWIQTKihdrTV02Zu2IsDvF\\n6ZVLFJKuHwUCUZF+gAIbLwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRDF6ZVL\\nFJKuH04ID/9Xl2jbyBsu+JHS3fsMDSZE0L39HhqbRKqrUxq5U9vb3aWU3Imf3Tu3\\nez8Sp/aThXOJKuC9QeJ2gCIe9+V+OGVYvUl67P3xxKzIUmlLlk5cbosC9m/J4MMZ\\ndmSok8XBgOWYWuNbcCNiW0msfDijJH1diH6tDc9UEzcTvTbWHqbl3S27uwVced3O\\n8OAY0MGcB6Tw1yRBbv7fJ4nWKeu3kmzrepRQYh9cEMEf+pDE0RUkoORiQI5vmtzL\\nv454PfNGGuGijMQm64tYqe33fwMR0marbLyYXTSMlzEDF5AxeaKjDVI4kEe6eUT4\\n8kLsvRl2nPX1gbrBSkHSZ21/oMkhdlGhPyb4xKcqCVkzpQJpCsATmAkjtp/IHJib\\n2mu6TzhAIvANP5jqiGE128lZpPBILq3PIrhXqVDyLWpl6xTSHz7rhxVXtDHJZoIz\\n4QJM7Dl9V0s/UQ5hJdmx5L0aEP+7b46+3kvgbPvItaRiF11L7fRQwXMNoI8bm47T\\nbfW5nJK8p6O5VssHtFYqL9rKYBDdk6JYsiZ8xvTrqTRMK1xJEsuF3Tuv73JmMQtF\\n7wQq8rZg0cbINpJuOBRsvEAo6ATJBq+HOCAuqvhJ3Kx9lixLnURP4dybKJoTdWJP\\nSDgLwly7bulTF+fHQSlD9cypaLiw4cyzFubhw4OWEJYMAsYcbfBqYA==\\n=i+xf\\n-----END - PGP PUBLIC KEY BLOCK-----\\n\", \n \"type\": \"PGP\"\n }, \n \"last_updated\": - \"2022-01-19T23:08:51.571224Z\", \n \"number_of_documents\": 2, \n \"number_of_messages\": - 2, \n \"remove_star_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/remove_star\", - \n \"replies_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/replies\", - \n \"submissions_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions\", - \n \"url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"uuid\": \"ae59153b-0871-411a-a72a-0f4c41a76ee0\"\n }, \n {\n - \ \"add_star_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/add_star\", - \n \"interaction_count\": 6, \n \"is_flagged\": false, \n \"is_starred\": - false, \n \"journalist_designation\": \"indecorous creamery\", \n \"key\": - {\n \"fingerprint\": \"04DD6C14755616B9F944F87311961223C70DEA58\", - \n \"public\": \"-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\\nmQINBFGRfoABEADEMD/A2IVlAmhB3Vu3jDlG3UFli/e20GXvfeW6S0PFEuvE9Po9\\nCjI43sFdMVvRUvtaIP5PE1zU4OuN1gi6jpKp5puulnddV6jP0GXqK+hqVXjiaf58\\nhUkuvpK2CaHf/5DvGdSW2IZLB9oP/UtWYTBUm7dER2Fc+rMY13fUMEsGKyJZ9wB3\\ny4CrJpMw7TNTefVx6vrlbCVEB4nksod+A7wteLILbeGj26D1A94vH1V4iLdOObW3\\npbTX4Yra1CpxclEsHyaS7tZ+4bQOmh0OdVG7ZW4MZPYp+1BIqt+e48042Rq1jIHu\\nHVApvHynPDt2tD/KiymDM3Bt69Dy9rHrWEFlWAS+Fpgo7qBQ9QF2fHWzpHQyhcTB\\nM3zQ2LraeOrBWgzjgCRIei+sga6w9Tjk8fMZKLl7HPkjRZxOFU4GJLjkxf3Lw1Av\\nCo3kQijDzj0nN/qyebcD2/v6vz5/5D8iS85fJdgLwds7ajXXgk9/M11Bkze1RT+2\\nYCmsUW999wF+AZmeR6ZFdUfcOpJE/99zs6GIRIo+ikPWiMcs4/7jAlrierrAtuhH\\nl6luFRIz6utBFWIleZosxnx3ZqRAv1DUdig3BnIliD3Y53y0cHbFFLOX428ZGKCp\\nJ9Of22l5XfMlT6B8NCJgRcQc77beedl+1XcQP64X+FgddottileDhsiRNQARAQAB\\ntHVTb3VyY2UgS2V5IDxHSlFBVTRBVUlOQVNBRk81R1I3N0NMNUpDWFRMV0FXWjJU\\nV1BKSExDSTRJWFpNRVFKWVlIRFVUWUFNWjJOVDJLUDdPN09GSlRRSkdTSFJJT1dP\\nM05aS0VGRU01QklHTkNWVkFFT0xRPT6JAk4EEwEKADgWIQQE3WwUdVYWuflE+HMR\\nlhIjxw3qWAUCUZF+gAIbLwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRARlhIj\\nxw3qWEDyEACKKS0y7ApY7CMGuuU6BltrUyc7A5UcCe6vnCREX4662qkHgaDLmIpa\\nb5t+hvtOicEwegoFsBAnjnG+Vs+AU1DDzXREojZ0T39Hyq0PYS7HbDWJRUSfl//Z\\na566rtbdzv1GEc7hMAEi9pKplR3uEQlQAp1G6W1Yzf5WuwmdWMOactzbENJTnbc1\\nSBe/oKbH56UEMX7KLr5MODQ6IM+VCqRI/k6Px065q8scAeEQERwUFdy33BBzk+g7\\n/uYPC74NnfISP6Tj94oFEySs1HC2hIaZlUQor3ZJOzvZ3Vm8hix7JdjBVdqdHFmx\\n5+Ft211Va6v1dKCUW73GPvYkv0bt4CeAV9fhyQOSMSENTiNVVh8L2+dCXVQXhFUw\\n3Hmu/tOj+r2B8+vWWHuhbFjgeAiXFkHFDT1a3xZ98n5g5SNwoiBJDuyWjPgr0vG3\\n/+1wgTovRVbt62H1VgRsP49wMS9EBz1DV1q60GcWD40FNfkJx7W1T0RtUgpKp3hH\\nw06RJFAzeMJtXz89mFpIQfkVwBflne5HDQywIT8o0TnxAh06Q4ROqhFydDSB0HTv\\n6NJVRhiSiwGmYiZi4DVwv7exttrfv6h1TX99MjR1e3kjki/IjeI/pW42GgFUZVN5\\nWRzx2yiSIfz1rhBqnRAtZWConlmG2X3LRbUFtz1LHsbC8UqKdtlB1g==\\n=oWMO\\n-----END - PGP PUBLIC KEY BLOCK-----\\n\", \n \"type\": \"PGP\"\n }, \n \"last_updated\": - \"2022-01-19T23:08:57.846667Z\", \n \"number_of_documents\": 2, \n \"number_of_messages\": - 2, \n \"remove_star_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/remove_star\", - \n \"replies_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/replies\", - \n \"submissions_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions\", - \n \"url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"uuid\": \"55fb95c1-cff3-430a-8c05-125c67c81a6a\"\n }, \n {\n - \ \"add_star_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/add_star\", - \n \"interaction_count\": 6, \n \"is_flagged\": false, \n \"is_starred\": - false, \n \"journalist_designation\": \"conjunctive lavage\", \n \"key\": - {\n \"fingerprint\": \"F71969D1705E2E3E374B95992DA6D8DCEE36946B\", - \n \"public\": \"-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\\nmQINBFGRfoABEADcaB1fww19PLIREowYKfNZiVoWpLYxRnw1U/Iz4JbnEJ7TuIlm\\n2Q46Hr9kR7zQVb5okjn40whN0JA3lJcfPZdjfxiCt8VYI7vacUxVZgXWJCR83vO4\\nNSD1YnZD5KXi0B6PGKIhry1Hqc+hzmMAFYGGdi4h5EKxinNmKTO+E3Zupeydm0KK\\nCBwXroROAs/5+s63oj5+nuqlPCTcEL3SGjH8zXIw+TN0mBhQhGlyqofIW/JEaviP\\n+frUL6WPa3AoUBE+TAF1rmXr30phZU271zfAYhe0B81gtrUTSg49uUYQuCf1xu92\\ngbuOmcYTQvdzgGDp8cNWL5cmQCdvoGTGH5PYodqMGcRfWqB1dl37RCsqDcCzssdv\\nJiUe8qC88n0tQl/gJOgniEhKEok5EiaGuuLz9j7waGB1aBgHLPsibDGQVyYn9ZYD\\na3E9cL0BHzsWJc9i1hFE2cmTXzmJ7rTXyvHSvidT6s2cljuih1Q6e5qNOcJPAuv9\\nY2xuZHn+rTaJSLM30X7PngrAP2jfepraz7zy2lE4Uex9dLQNPMcYhjPc9SwKjk8g\\njDkhCGW6daRCpzNUR/ydYGlfN00L6MPo0S3XG/x88f+OwqgfSpgrfSijqDTLxbo1\\nO4rTW+KSiVy2P9DfuLhZv+HcNiinY0EP3qbuuXKk7VSMeCir+HgeDce+pwARAQAB\\ntHVTb3VyY2UgS2V5IDxTV1pWS0hOTlBLQkIzVTJDRjNBMjRIUkJZRlRNNkNDU1U3\\nM05XQlhNTkw2NVFRWktEM1gzRllNTFVDVlBKRlhCRUJWRVkyQklKWVJLUUQ2NUFT\\nS1IzQTNaTVhaMkFOTkI2Sk1CVEJJPT6JAk4EEwEKADgWIQT3GWnRcF4uPjdLlZkt\\nptjc7jaUawUCUZF+gAIbLwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRAtptjc\\n7jaUawViD/9O2J9EsxOmaSB3XI9q0EyLvOZPh+r9TeOGA4kqQlOH3PeMP1lxQ7v1\\n3LR7OCjM2pBNHww7rRkYNoJX4dA/UjZ1UcerIAbxa2Z4v7X69akKItw889UCW6Go\\ncUtco2XqkjaThsV/io19+6qFicrWAumpFtH2Dt8iVsHzOYWpijPK70AxJqODg+nK\\nv4k/+zqAePbLOCCCuvnhBduJCEd3dA0G7ow0H/AzgpPKOEswbYK6JJYX8Gsq9F3n\\ne+PkBJ3Op4/qUELYQYEBbF2qy+XPfhOZsJ4v/HDb+eutZNmATtpGZGNJznyLFoZX\\nbNI/U2XIlQYBDeYTOVbNPPVwoVucoXG1iGsp+2ZFvLgP4XGRxdH9oyiia9FC+id1\\nwCtS6dRWRKv1VJwVetGBncAdwmugCkQoJ/gGwcTkJLhOVyoZZruTR8aLOE+ArTUg\\nfgKBVpeT9he8ELDZFrPtAnDTpMS+RrVsF8Y1sih7O8VCxsxGRegKlQcxgPp7/MdG\\nwFOlulTqCSu+fZfkid4rvnRGcPRp1DQohwXiK/UpDIRYTPERHQTEm2fK29FzmruI\\nr4zotTaeHhztY5jrqZqzkMy6/teHE5CGq5mKQsXzQFjb5hKEYg4TwAazPRtH3WOo\\nkZ5ISlxKvOdf8jA9hWKFrREtk9t9blD0IA3ffzfO5aad+aZjnqsgyw==\\n=ccYc\\n-----END - PGP PUBLIC KEY BLOCK-----\\n\", \n \"type\": \"PGP\"\n }, \n \"last_updated\": - \"2022-01-19T23:09:00.294006Z\", \n \"number_of_documents\": 2, \n \"number_of_messages\": - 2, \n \"remove_star_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/remove_star\", - \n \"replies_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/replies\", - \n \"submissions_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions\", - \n \"url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"uuid\": \"50c5fa95-eb69-49b6-8599-62b12cff7d7d\"\n }, \n {\n - \ \"add_star_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/add_star\", - \n \"interaction_count\": 7, \n \"is_flagged\": false, \n \"is_starred\": - false, \n \"journalist_designation\": \"sixty-nine alliance\", \n \"key\": - {\n \"fingerprint\": \"7034A99B359CA2DD3F57E251437B6C3C6984302F\", - \n \"public\": \"-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\\nmQINBFGRfoABEAC8d/LgDtvyeg/SNsUcUPRY7JZGFbE3peoduYiqd29LW/BXoInn\\ntRV3Ks5H8QLH3/qS/zWwiE4x2yE8cOykWj/lPMlFCDYdWK4f55eS1LcxN+WtLiaL\\ndDQG84KICZznbqTxlvdizLwCvch9Y19dPszPuwrBJ2KbOsngPfHDARs2aU++J1d1\\n7MjIpBLJHTlYKRdutANtxEKCq+KX9/K8GnjZYLhmmecaVr6OoSp3Nq6zlvJe7qPb\\nc1IUJhA1oDyNVBAPs5ROKkM6qhDJmI9OpKoGVGWG7u3kDQ3Oo59wBoC65xTZNFy1\\nGKcQbCcegKsnxdchBO9nMK3wh8H6JUkpdXPrurysHqQ6JIAar0rXIlOvg8kD6yNU\\n7bYK6xetBzkYBGgz7vbgYq+k2ur3nQLvJmBnPVqY/7bjSGDIfbkJWOudD2LaqQUc\\nIUeBpTlOsqfVhXwfen+ynntPdSQU14ILmQAztFzZor2leNWAR6pYG6ZI3vEzAX3l\\nWPzmS7L13VC1w11IG0wdKuzhx1jHGJ32JrNyL4LoJ1O++8GWlJS0+ZC85gwIaFQC\\nLB+sGw4PruxLUGFe2ZLYWgYnN3Iw5JBPxfc+Kxrp1xhHCZNdC1B1ajtkOwvdZbIU\\nOP9Cp5MRt5AeGBZ9ujIMsAxOZrPeN574ewqnY+z431eC6rNFzdmlY1Av8wARAQAB\\ntHVTb3VyY2UgS2V5IDwzSjI1UlA3NlZUWUwzVktMV1haTENOUFI1WUZMQzJQMk9Q\\nRFRETE9IVVFQQkkzN0RZWE1CWkpORFRVSkxSWjNDUlc1RkdXVEJNSDY0UTNBN1BZ\\nTk9KTjY0T09YSFpRRE5STDNRWEVJPT6JAk4EEwEKADgWIQRwNKmbNZyi3T9X4lFD\\ne2w8aYQwLwUCUZF+gAIbLwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRBDe2w8\\naYQwL7osD/9nj9I/89AR2p+MDw+RqGjNrEMnIyCC1+IneGC5MJXLYb/9oz9JRMrb\\n/+Gk+MhPjkgHVbI9BzByIzNh0stYF1T17rJDIyehjfbejYQKFwJd1+QHCfSgLIQQ\\nNOtKKr9iX5fUdPzlLzkdaTRGMidUTqWuY77wgmZoKN1a1Q801NXjIkY3QJ5GpjSf\\ncdvgu77k7y/0juUu0eTeNpd1TXs/GBitETnfDEKcVUkk8x+OwvSFE7VrWJCNAH/x\\nOAQUeT9S7CczoUeFWCII880xFcpdynt+ogYyxVh22RV13HJ/HJlmUA+9cpQ6ntAW\\nXdhKS814mJjqfTk5j2ZzLwKekqQgUSjCB7ucbEPhaHdQHShfuNQg9EhtP2Qy+Ptg\\ntGFMF4f+s9anFobioeYnS9S3JuR73UHD6XOz4GDgGx/3kdlxwRfjOqnRWzC3oNmU\\nVmT2caEmXnjEqL3FP1wVOEcciBqOAgT0QsMB06eOHL+cJxMOE6j/Wo4Y2loF0+Bq\\nR0KMqbg0lpSyLHjTmOo15DgzohSALI44niM1SaVGGlzOawb5zOd8ownvfwcut1wG\\n0UxhwbyoiHblTySzzjhekJQGMGQOyRUIfbjbNtHKeVFVEosM5dUhXWRA+8n1uhc+\\npqdAhXSd9yEIjy8dIc7USlTTqEEOYYXetEWYJP6tolKuggSiiUB49A==\\n=9Hjj\\n-----END - PGP PUBLIC KEY BLOCK-----\\n\", \n \"type\": \"PGP\"\n }, \n \"last_updated\": - \"2022-01-19T23:09:01.659060Z\", \n \"number_of_documents\": 2, \n \"number_of_messages\": - 2, \n \"remove_star_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/remove_star\", - \n \"replies_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies\", - \n \"submissions_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions\", - \n \"url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"uuid\": \"92b1914a-1b1c-4674-baad-1fb662aed682\"\n }\n ]\n}\n" - headers: - Content-Length: - - '10778' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:29 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/submissions - response: - body: - string: "{\n \"submissions\": [\n {\n \"download_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/48bcb4a3-6f23-479e-a718-e0b93fd4b9c1/download\", - \n \"filename\": \"1-concrete_limerick-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 611, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"submission_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/48bcb4a3-6f23-479e-a718-e0b93fd4b9c1\", - \n \"uuid\": \"48bcb4a3-6f23-479e-a718-e0b93fd4b9c1\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/d8db9ba7-4789-41c8-9f7b-3761a367816c/download\", - \n \"filename\": \"2-concrete_limerick-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 757, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"submission_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/d8db9ba7-4789-41c8-9f7b-3761a367816c\", - \n \"uuid\": \"d8db9ba7-4789-41c8-9f7b-3761a367816c\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/648932a9-7e82-4fde-a65a-fee812b50ec0/download\", - \n \"filename\": \"3-concrete_limerick-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"submission_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/648932a9-7e82-4fde-a65a-fee812b50ec0\", - \n \"uuid\": \"648932a9-7e82-4fde-a65a-fee812b50ec0\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/e0565187-d9ea-494b-8ea0-173befacb1f3/download\", - \n \"filename\": \"4-concrete_limerick-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"submission_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/e0565187-d9ea-494b-8ea0-173befacb1f3\", - \n \"uuid\": \"e0565187-d9ea-494b-8ea0-173befacb1f3\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/ecc07e49-be88-40d5-8e99-bfb3b3812668/download\", - \n \"filename\": \"1-indecorous_creamery-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 593, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"submission_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/ecc07e49-be88-40d5-8e99-bfb3b3812668\", - \n \"uuid\": \"ecc07e49-be88-40d5-8e99-bfb3b3812668\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/c60627e5-dfc6-42dc-8874-b290ef09a2d9/download\", - \n \"filename\": \"2-indecorous_creamery-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [], \n \"size\": 595, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"submission_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/c60627e5-dfc6-42dc-8874-b290ef09a2d9\", - \n \"uuid\": \"c60627e5-dfc6-42dc-8874-b290ef09a2d9\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/0e734035-3193-4c94-a86a-41d04332d8c0/download\", - \n \"filename\": \"3-indecorous_creamery-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"submission_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/0e734035-3193-4c94-a86a-41d04332d8c0\", - \n \"uuid\": \"0e734035-3193-4c94-a86a-41d04332d8c0\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/93d72061-a8f5-4166-9a7a-3beeea4989e2/download\", - \n \"filename\": \"4-indecorous_creamery-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"submission_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/93d72061-a8f5-4166-9a7a-3beeea4989e2\", - \n \"uuid\": \"93d72061-a8f5-4166-9a7a-3beeea4989e2\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/f2fc98d1-8acb-405f-a4c3-c93bf23febba/download\", - \n \"filename\": \"1-conjunctive_lavage-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 638, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"submission_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/f2fc98d1-8acb-405f-a4c3-c93bf23febba\", - \n \"uuid\": \"f2fc98d1-8acb-405f-a4c3-c93bf23febba\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/4abcd4b4-3922-4ae0-ad97-9186f51e172c/download\", - \n \"filename\": \"2-conjunctive_lavage-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 667, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"submission_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/4abcd4b4-3922-4ae0-ad97-9186f51e172c\", - \n \"uuid\": \"4abcd4b4-3922-4ae0-ad97-9186f51e172c\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/2281fccc-4cae-4228-a837-e6f3a3e1e6d2/download\", - \n \"filename\": \"3-conjunctive_lavage-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n - \ ], \n \"size\": 661, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"submission_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/2281fccc-4cae-4228-a837-e6f3a3e1e6d2\", - \n \"uuid\": \"2281fccc-4cae-4228-a837-e6f3a3e1e6d2\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/098a7d90-0ae4-47cf-a7a2-2afc00094a3b/download\", - \n \"filename\": \"4-conjunctive_lavage-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"submission_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/098a7d90-0ae4-47cf-a7a2-2afc00094a3b\", - \n \"uuid\": \"098a7d90-0ae4-47cf-a7a2-2afc00094a3b\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/546e7e6b-ac50-4ba7-b738-82f0d261feee/download\", - \n \"filename\": \"1-sixty-nine_alliance-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 591, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"submission_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/546e7e6b-ac50-4ba7-b738-82f0d261feee\", - \n \"uuid\": \"546e7e6b-ac50-4ba7-b738-82f0d261feee\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/987ef070-4e9e-43e0-98e0-2c623607aae1/download\", - \n \"filename\": \"2-sixty-nine_alliance-msg.gpg\", \n \"is_file\": - false, \n \"is_message\": true, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 591, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"submission_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/987ef070-4e9e-43e0-98e0-2c623607aae1\", - \n \"uuid\": \"987ef070-4e9e-43e0-98e0-2c623607aae1\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/2df5a904-e89a-48f9-9e33-5b9759317f1b/download\", - \n \"filename\": \"3-sixty-nine_alliance-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"submission_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/2df5a904-e89a-48f9-9e33-5b9759317f1b\", - \n \"uuid\": \"2df5a904-e89a-48f9-9e33-5b9759317f1b\"\n }, \n {\n - \ \"download_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/03d1920d-d4d8-4580-9c42-6333c812383a/download\", - \n \"filename\": \"4-sixty-nine_alliance-doc.gz.gpg\", \n \"is_file\": - true, \n \"is_message\": false, \n \"is_read\": true, \n \"seen_by\": - [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n ], \n \"size\": - 661, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"submission_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/03d1920d-d4d8-4580-9c42-6333c812383a\", - \n \"uuid\": \"03d1920d-d4d8-4580-9c42-6333c812383a\"\n }\n ]\n}\n" - headers: - Content-Length: - - '10192' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:29 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/replies - response: - body: - string: "{\n \"replies\": [\n {\n \"filename\": \"5-concrete_limerick-reply.gpg\", - \n \"is_deleted_by_source\": false, \n \"journalist_first_name\": - null, \n \"journalist_last_name\": null, \n \"journalist_username\": - \"dellsberg\", \n \"journalist_uuid\": \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", - \n \"reply_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/replies/9bb8030a-8561-4a03-85dc-e921bd6a891c\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 1138, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"uuid\": \"9bb8030a-8561-4a03-85dc-e921bd6a891c\"\n }, \n {\n - \ \"filename\": \"6-concrete_limerick-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": \"\", \n \"journalist_last_name\": - \"\", \n \"journalist_username\": \"deleted\", \n \"journalist_uuid\": - \"deleted\", \n \"reply_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/replies/0a82f046-581c-49ef-9b51-ce5b73e45c1a\", - \n \"seen_by\": [], \n \"size\": 1284, \n \"source_url\": \"/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0\", - \n \"uuid\": \"0a82f046-581c-49ef-9b51-ce5b73e45c1a\"\n }, \n {\n - \ \"filename\": \"5-indecorous_creamery-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": \"\", \n \"journalist_last_name\": - \"\", \n \"journalist_username\": \"deleted\", \n \"journalist_uuid\": - \"deleted\", \n \"reply_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/replies/1c2ff7fa-252a-426a-83e9-5840cf657739\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n - \ ], \n \"size\": 1120, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"uuid\": \"1c2ff7fa-252a-426a-83e9-5840cf657739\"\n }, \n {\n - \ \"filename\": \"6-indecorous_creamery-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"dellsberg\", \n \"journalist_uuid\": - \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"reply_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/replies/5f5707b7-ee1d-410f-94be-1ba8c1929264\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 1122, \n \"source_url\": \"/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a\", - \n \"uuid\": \"5f5707b7-ee1d-410f-94be-1ba8c1929264\"\n }, \n {\n - \ \"filename\": \"5-conjunctive_lavage-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"dellsberg\", \n \"journalist_uuid\": - \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"reply_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/replies/158dfd73-3cb3-4a6e-85b3-f37ae54e0802\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 1165, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"uuid\": \"158dfd73-3cb3-4a6e-85b3-f37ae54e0802\"\n }, \n {\n - \ \"filename\": \"6-conjunctive_lavage-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": \"\", \n \"journalist_last_name\": - \"\", \n \"journalist_username\": \"deleted\", \n \"journalist_uuid\": - \"deleted\", \n \"reply_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/replies/24fbb6b4-504c-4fa7-9971-e6f2d1447a48\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n - \ ], \n \"size\": 1194, \n \"source_url\": \"/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d\", - \n \"uuid\": \"24fbb6b4-504c-4fa7-9971-e6f2d1447a48\"\n }, \n {\n - \ \"filename\": \"5-sixty-nine_alliance-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"dellsberg\", \n \"journalist_uuid\": - \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"reply_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies/4dad63f1-dc12-4162-9c59-065c88b2a8b4\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 1118, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"uuid\": \"4dad63f1-dc12-4162-9c59-065c88b2a8b4\"\n }, \n {\n - \ \"filename\": \"6-sixty-nine_alliance-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"dellsberg\", \n \"journalist_uuid\": - \"dfb1ff22-a373-42ae-9c40-28e04b08548d\", \n \"reply_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies/d5b658be-aabd-4d7b-89c1-51de7fa246a0\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\", - \n \"dfb1ff22-a373-42ae-9c40-28e04b08548d\"\n ], \n \"size\": - 1118, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"uuid\": \"d5b658be-aabd-4d7b-89c1-51de7fa246a0\"\n }, \n {\n - \ \"filename\": \"7-sixty-nine_alliance-reply.gpg\", \n \"is_deleted_by_source\": - false, \n \"journalist_first_name\": null, \n \"journalist_last_name\": - null, \n \"journalist_username\": \"journalist\", \n \"journalist_uuid\": - \"a9f8835b-52a6-4845-b428-61cc10561a0b\", \n \"reply_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies/f774fd7f-55ad-45a6-9a92-05053f9628bf\", - \n \"seen_by\": [\n \"a9f8835b-52a6-4845-b428-61cc10561a0b\"\n - \ ], \n \"size\": 1605, \n \"source_url\": \"/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682\", - \n \"uuid\": \"f774fd7f-55ad-45a6-9a92-05053f9628bf\"\n }\n ]\n}\n" - headers: - Content-Length: - - '5844' - Content-Type: - - application/json - Date: - - Wed, 19 Jan 2022 23:11:29 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/546e7e6b-ac50-4ba7-b738-82f0d261feee/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqARAAmwUjOf3oGUcC5K7tSj2wxiaUdEVeNF4vF3dX1fehU6KBpQhv1Fq1RkRg - 1xM0d/QOpfw31CX3ZS2hPdA0YkFt8xCNHi2UYY2Klumo9clEx5TsyF2xQ0YKSZ5zNlqVJWKRpa1t - bhtG3nRC7KQfEsQNQyLgQM/l9EJtzrYoYJEgd6vj9m8kPYsPhNnX4xtV9I4CFam1fwKqdJvjRiHd - 2v48TXcqxYywEwUKyrPyeLUvhFaPfYX3d7QVKd94Wj9FUcccV3Sn1JNeggVKuyo2i4k4ISkGGRr5 - Dr+Z7WVOTzZ2A/Ec7X5onGDbi1XGlrK94PaOEe00ER8sSqGQKDmfTu/RgHp2vwi5hvBUtOy7171f - 5lf16EIXP9WzNq5svfBBcRSiqTAXIIZ7L1gT1XT78edb/1UTAzj8MWv7AjOCWX893AzSS0QT52qb - vtdFygfDSLjTlOLS5S5mSwXySnTMEWgxtr7MEMOiNOiYmL/DGlHHMBv+k0KwcCj7UAQ6Sxs5Ek2V - nUP12NtHqUv50LWhIx1sec4SlinNwRyUXlBz03ZKazij654snOziaTHIS5ColH1Dybymz04FjWsZ - 1g7J09SSwH2SFCX/ZC/F1+DrJf6aXvjBtS6K1jB0179vzLqtOc+g+IT4R7RGZoc5SJNcIwNzSAhR - Psvoid62jXUBMluHUGnSPgFsdF4s8vKoV+3hb12cuGou87Qthv62oGM2k5aX2KHk/AWAcQw4LeT+ - iYWJWWBwFLOt2WUfZcX+rKQUquZi - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=1-sixty-nine_alliance-msg.gpg - Content-Length: - - '591' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:30 GMT - Etag: - - sha256:c2f54737913721bc1c2984e1d18ff6e7c21633f61d6e6cbd64d55367d4de1aee - Expires: - - Thu, 20 Jan 2022 11:11:30 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:01 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/submissions/987ef070-4e9e-43e0-98e0-2c623607aae1/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqAQ//aY9hxX2ogbaW32nmX01SSuMf0f9p/d916Nmkjcy19fl/FJYYuicgocKt - /sae44rGh/mrxSAPlujS9BA+kFAaKC1mHvIKwZNRIX95XjjOXj83ndEju5DEkWpS10j5fVQ6JsMy - HV71GP5RZpOvOd6h7MB84MtKsKwTNRiuafeRaBdYWsT+RfuAURTHnWY3PpyBFDYwqlh3UeRdJfXu - J2XSc6H/2071WCOFvJqD47fkdtD2ox+pWXjP4D4ZDjNRqx2apSYqdQWmDuPM9cxDbIMbELnoZZ8R - /e0hgHzbEq7bTwytpyZKnW5fdx0MWoE1GL5l9a6Yr8HdzzbOxYO3vYCf1+gQCDX+/4pRQePzS4+r - 7lJGkIQ8ioaX5ow/nDlllLqEXsHxybCI8du+a/DvlDJrpf7ZcfZRGpsOyU1w0+ZTizPfknMaDK9/ - xhhBt1JU4huxZKH3F1F6y9ws9tVIcfk6eVRkWRbvcVIf1W5yPb3hGPwZe8TpQmp4EgG9Ub6ExLjc - S1lyJ5IVBm+MUy12DRUIHKDU9ZEtkCcqZ9WdNj0FeUGiCUg6Q9ODrOVkuX53JVHwbOBMpOu7Az6h - Vb3CCImEt1VKsPRNNIMdJj4OiF0ycUwlIlZNtTvhP737zjX+FKx7fA8WhusxvrxN7bWj5YHaJ6ur - 89WzLagmFrEBFNvz7Y/SPgGyUwWol+H/UJhuwiMxQPzXQZFSMVaf8kNud+FEcsVwLlr+7RxltIUk - Cg8CSW0Qc7K0zX+aT1t1ybpjAxAU - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=2-sixty-nine_alliance-msg.gpg - Content-Length: - - '591' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:30 GMT - Etag: - - sha256:c8d979c2a5ddbe1442b987bf52676c27952972e9b5cfc65e8725808aa0c00ece - Expires: - - Thu, 20 Jan 2022 11:11:30 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:01 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/f2fc98d1-8acb-405f-a4c3-c93bf23febba/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqAQ//ZGSn6Joprv5rISp7I9pxfmNwnQywlsFX1PCfQd9yWWVg0BBVIgEp1oe1 - 8d5CkW840whZxhT/+2RIqDIHZ/sLXJabXXDa1NIYBLCehXbkFvZDTBeyuxWRxk0QPFLlyB8MYN6c - 3MbLOsyjppgQS4wtcYSlcDva5tuYn0wnlWz1DEUAAgC1mfuNa4AjlfEDh6pN+52tq5ysl9vE3WHA - CHAuw5Wbql3NhJgjmWBCY+5OirTUWz+UBX+XhyPVD0g1HMD9mbpbgUFhuBOZt68YNPBdrtosLKp1 - c7PdajSwRqmE4hx2s568npRbFjL9l4GpGAcLef3+hjCfK4kTb1wcIsEcZX/dptfId9Ny4opzos3S - r/v3TckuSbzWkbO4sLgjFxR48vByIvB8DgDPTLF1wFn8KjmRI9uy3+lvjjhQ4FecRceYOkZRKf8E - DOzcGlbcxQMADYTUkikD48fEeVp7GrqCcamdT5xtVK1EC5BgrU411KNV9W98rWAJKiwc/ZM5TlRg - A7EaVllksthnB/R2nt7wYXB2yhi3iFOQXWOXvgyp+TEAtmMGXZXxhOCAPasxiiGk5lssxmckhgyJ - sEZY5vkrcUgEp6rw1afkDpzrcnKYxe/B5e3nxzB4HY8/VoNLuV0qCsyn7KF4QQgeFSblbbPrXGa3 - avOREyv2eBcOX9INYBPSbQFIF34xe1cmsu9LRxvJtNw+7L2jfbAt/p+K0uWbL2iWGAzWOdIz4ER3 - ZGE7ejn1FV5LkUiusfADKIvWh/Jcf4rRSY5noaaUdBkyT0JDXWLPvbANUZPIOysB/tO36MRBBdTF - fq8mcxnERAHf5Ok= - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=1-conjunctive_lavage-msg.gpg - Content-Length: - - '638' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:30 GMT - Etag: - - sha256:369cbfc86fb18c430582307d6f64110de459504027b3132883d89ab50bd50ff4 - Expires: - - Thu, 20 Jan 2022 11:11:30 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:00 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/4abcd4b4-3922-4ae0-ad97-9186f51e172c/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqAQ//bwoOwi3Zwszz1n7ylgcD++Vx2S1yUzLOqNi8KWe4xAJSCaJw39dcbkiT - 1OqJpJDWwIjWd1yRIoeLqH21SX4+PWt2Ra2j/MqjsnQdmXa4hEqdnTgaiLHXC8DvUF3Kk4YfJ2Ro - e32INfFkpT+AuXRSZFTmVlmzFYKTEvlnAGhOGubEbZPc0/pWZt2f9FlnVbHGTYeiD7mZfxmpwVTL - ilTxm0nAZMVsv+sD/f4yLoYn0f34e3zMwWgWFJ8n5G0Avnhkxq7NmzOLeAIcmY+jA3enYAUrhCNX - SXWgI+sUfNh9Fxyp+2DkXtW3hEctclLyIpSmRbMSfhGdUbGSDlRwyrZXZXvE2GkE20xiFbilnhjw - dIsgCwGWjIHduH5S84+l49bbAQ3lHnaQUzrIBM5CAipsubdp4UJQW5MH+QcEf6u6P4YS9PhRs6c3 - oFRoCAvY9mRSXe1iqjxE5jAXQeKZkZGzB3AJdoBrzM6ZsOFXPALJy+eKk1/k1NrR4md/MUtAxsej - V3CIH96BC8GUNMXAaEzHAd7aOEN4acdT9QY0uua9cq42bJ7Em3zpzxG7x30SLL9eHvYuGSqeJr5T - K1HF10GEjdQBzpR3PBl0eFwO0qjqW5YBQyHB4+exT+vVYJ1sSeOQor5yCFDDxjplYDonYeQLJOWl - fkg3UPOpFbMvB21nCRzSigH1RFaR4mU110vETzz+BSfNqDawJdGdtsvgo/qjszTVhRstgSSMRJkP - Oi5gpNSjAKP4oHwSf1YS8EPdA0lnR1/keAlNkIMfogWicxyzegEbkFFVdvxZDw++a3rdFanSEhqn - B/y6C4BhoY0kF3V3RbHUG4xB2voOTgdqbuB34EjiXqg13epvVzH5Ng== - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=2-conjunctive_lavage-msg.gpg - Content-Length: - - '667' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:30 GMT - Etag: - - sha256:d92a7cb9901368d8ce9478c1ee67a9becf3789330648c801de9070b5d1c38232 - Expires: - - Thu, 20 Jan 2022 11:11:30 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:00 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/ecc07e49-be88-40d5-8e99-bfb3b3812668/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqARAA0bqrq1QpF62ZAMgrtbCo/7kmm8IGB/7Lddclop2NH0P4BEOO0yCFruoE - oh/JvsHnA1aOiB+OWUba0jqytICNts/SmkUCMGawCvB4f0mCFTwqnPKZolol1juhi+v0Nj0I4No7 - FL8hYgu4OQnUJoUaHnk1G27QayFc8bpA/uIqD3Wc7vy1stVmjIbwRZibEUgUThiW05jvPST7bCcf - a91lPAOpIB7n3jY43omHBfCnwXlhCmkl5ruyKJK0a6buP0UlZJv0eMNjLJ8cIZmIabOsKYJT4JGD - fXGJ/NBOa0Nv++crzLYu8tL+8iApEdyegHsKpzKDoT0t97IemCABPjLi18ZRh1YRlrOPKSre0HeE - 94d8fylTU3gP/j0oWt9tDxhMuLyqAjqfB5OvwNyO4Q44UovqnLdiCQvkTKavmXlfIoQ+mex6jlbD - AbPj5zwPU1ms+fqZ5BMNWagpuvGpW4+uDG4yQCbwKq0OWtdqMC5Ml/NC7bTXdowAUTZxcK4L1UZv - 8BliQ0bS8jKsFLC26KEdO9kHYwhoUVhJI6sS8IFTUBRpfuw7sc3ucjGC9a9Vbfc2ytTnSA4thwcn - 7kE8ElvDn1lpOx74+EeoGAksYQTw77FAf0OwYALZ0MlahyzxcZeW0WUShR4nUFkfwSghPmMYwmOW - NgiAEgyTB9G474RoPLzSQAH3kq3MXakzuGOxoH0BJyCV7pjx3DdpQxlg/PddYwURy1JO/2aQlEcd - dDew0WaSU00mRSf187RA0izsOoPJZGg= - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=1-indecorous_creamery-msg.gpg - Content-Length: - - '593' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:30 GMT - Etag: - - sha256:36167d9be8bd62598eecb1b8cc4f7cd2e6571141907ab2ff46a3add6c164fb96 - Expires: - - Thu, 20 Jan 2022 11:11:30 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:57 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/submissions/c60627e5-dfc6-42dc-8874-b290ef09a2d9/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqAQ//QX+Kk2k7xQF0Izm5HeQ5s5yL46DBQOX3HFSVih7JkpcjVGWREQyAfnOa - UgsMZ/sxJzKxLK41rRDMNAX2tWevCXoJdULFntJ1RQkUhNcqs1h9MPnavQxij9qSmaLFiEcfaSnk - jBooeYToIKaZ2jw/krVqqa57wbQlEexGMc1wTlfstEdmN3sQ70bZesNXBN7Cqv6HpVLbwjhhYXnw - 3mBjrCNwajvKVTW8kZvW0w/bufTewd4HYjycS+LlL0vtm6gNS1L+6FrMHktMjKyv0v4Fb3W2OQVu - hCVWvXccSY7Bv6cBNhiQOu9TcsR9MYrCSEBx7PTB2elznj3rcGsI5NTTcbt3mDqMlqSzAFY6JggH - riUPbNiiVwbGuMq/1QCpuHm7fSuLfxcEJCWbMhWBiYGbx/q+0YuuVnAwq4ECpo9OU/pWawUS7MqC - E2FktiBBlWJNlU7l3uKA6NpF2Reo1tsdSBsSBxg9JuU8hmein+PQtDgiUfqxb/z5OynsbKgEErs7 - 9+2uWvTzZB4N/4D49RcJQC+SY9rR6a4+bY1acVXF6lSDwvgrmdhtYRLh206Kk7GLyWWlW38EPB1v - vG51N48usjrAIUZGwyftERf7eZyqQGQeGCEqxBkjnTwACDUuEwNFuHDcEPgE7wFlM4vUzqnvbJRL - y9Xh4po9fRm/aUGQ7QjSQgFGYkMyvxrOBNoz2u8GYFhQcOZsBwx0s/pNwWHzjtqTFWu5QYG6kHmz - NOMplDrqSg18sbLUra1CifTy2uGLP7+EUQ== - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=2-indecorous_creamery-msg.gpg - Content-Length: - - '595' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:30 GMT - Etag: - - sha256:49c83b1c967bf7f87885f8a9e50e375c297ffe1a0f4b4369775f87a1d761d5a2 - Expires: - - Thu, 20 Jan 2022 11:11:30 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:57 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/48bcb4a3-6f23-479e-a718-e0b93fd4b9c1/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqAQ/+N0q7FdEEMxFB+ckGtjSjsKZpRrDlSd9P9hQNspERIrjrUL//aTlkRuyC - Bf+MtKJwjHl5QQvwSCmK9j+6tx2r1mtVBAvjB+Cd01Hr23buxhZ2nILVbCjq4lNwdWbbxYf1B2BN - VC38P3+hzfoToDaBYqPY8o98XeHxcn9ogqg7BXF73lHcum1A3Orq331qzrdnd5Hc0uk4euCytLIj - HvLLOt1fahV0sem0GwJjKgKcw3KNYElUipL82TUvVXmM4oxUSRbx7c1qvmMHE3RAvzMmevZUV502 - 5hzDJjtjbdSjwEQbsGTvmAy8Hu8nTIKmqZnLUNQAeNMLUiS9P/jy9eXn0EuOyNL7IcAeFZx1F5M5 - VekU1FiIFWM9ialJT9+muMkDUsgZqaCXQANzNyQDOvankAfDwLJYZtiUXCXAwI5QVzK9PmGotWii - 1DLqR1Rq26WKe/trbztyI+22Vkow4IJVvKSlzFftnDML3C2GnsAbo5+vwMBqkAX4F6m8VBeeMeem - ylDCh8bq2BoibodzbopQsKPZHcbsD14Okno7moKH3OFUReGqi+a7GDMJvN/XkEIRWjTDPnwWlfIU - rXZzpkZCwwDgrflLRVQoUBvQ3gu2+4T3/xE0J7kEFMR+qjlMUVCQFIQAfoTELFIlTOaN9a4T8Xg9 - l6XTUfpvJnz0PZ7s56PSUgGngyQhpYO4x6gHOBLO4+OLJSYshdB+qNB0iTLoJwjj6Spe3u7TTs34 - XQpIPp466dFfsJclGaqGodCghkn+6OYUt3pMeTxX61meRhYjpgdceLE= - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=1-concrete_limerick-msg.gpg - Content-Length: - - '611' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:30 GMT - Etag: - - sha256:2d4f3f0281c2b3da41855bafc3c90d3c1509d7f7b2cff3456c55a2b7efec5e31 - Expires: - - Thu, 20 Jan 2022 11:11:30 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:51 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/submissions/d8db9ba7-4789-41c8-9f7b-3761a367816c/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqAQ//d0r7U80dRHjHvMi5LkGOjtP+uHC46RsTkcshCNSH6++lYRWF8Y7USW4x - 66I8tWPIuuCIs9GcooUKO4b0kLz9NJlu0znbaIJN2OPeCJQ4GsQg49aPzTh6aRtOVt54sr9Lzlgu - d75mTqLtgMriTPKg8047lTxw1430feJdKSXIIPgce2S36CPPmS/yXYQOLMnsdvnpJ0lUkjSU27hb - PnF46hXehR0MKUArrSqeKAdOGUfkXHW13Kzss8tEvcfRlClz9gHePp2lVSvN7Urq8jEwt+EAQIJ8 - EKEGMVgdu+hQenjoKoubG0kP7trTg0gWdYP9jfprQEznCFIsDi7H71U3ek1o/eZz3Se1gkrxTDf4 - 3cTIHRjdw7szTjwO3jGIWe+PslKpMvPm7xxDI7LUk/7s4NIlMIPmHPEWOek/GrwCf5yp0L9554Ti - 4FF4LQwCposVIAmN9Haus6iJdAj3Br17tbkdW+SQmuZ9goRSotlA+mCMLDTIxnPKZItn53m5zHBy - InK+vOdre0gmCs40O+z5u2TPNw4SflxvJbk7v/jmoWMcRlURt+JajxpNPko6zluuRxJyNM3Qn4t7 - gLHmYIKMwjpr9RdHrPkSwxQLzAcW+DITCl6crxRTibi+QQIEz5bSf285lwby+66xdzgqX663KH5Y - p0dV99rZgiLwlpl0PHLSwCMBS9rTj0edt0rrwikTltaCqj5aOsOdCTYH8SQeSOzU9sreZbrLLAJu - ca+7tsvRFAQDl+YvIxN9UifQI2h7Kyma5F6EGOQ+OlAdpPFgtN2lKnX/5LLIaEf3M4uU+BPX+Rem - fPHbDPy/szIORpdcLA6z7AYk/a4i6ngzmBdqEGhXaBqkeVItHR5beyCcks++evNGECfcodK4SLDA - 14pFiLtnOAIa6GzJHpI7uiK4mPUQk+2ccMP2pdhpt76XVpShKkvAgjTexaZBZ3ELKwQDVZOOYf5d - 6FmaxpeN5Tx4/hQ2aN0oYA== - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=2-concrete_limerick-msg.gpg - Content-Length: - - '757' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:30 GMT - Etag: - - sha256:9253415712bbff3a68beddda5f93781c81399d5639f7f14a93b49c8fd8539ea6 - Expires: - - Thu, 20 Jan 2022 11:11:30 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:51 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies/4dad63f1-dc12-4162-9c59-065c88b2a8b4/download - response: - body: - string: !!binary | - hQIMA0N7bDxphDAvAQ//XuxXLagu7zv1n7lcws75pYK8tSmE5tH3eqDw9imBkXqOWtutqRX3E9YB - EKvcPoTSZwAxhU5vdHuWHtMbglo6no6eEyzVXnSUHUzr4Pdzv4uL+0prIX9q1u4b30qsZ6wmdIOt - KkGav+8P2ifFfGvleyCigFBV/ipIailap8mkDIKvxGRmAmCQqCJHiUpRNe6QkEddaBLwdcfOzubZ - 4XxsaGwYo0cYK30+NP8LCgnDtSv7la+mtd+qHVylkascHnGL1nHP9yFbGTxKZ7RvlPixo8qMc1Y3 - INLmgKyOca6iDyH5swWWEptE0AU7fPi8ghDhtXZv8jEknClZM71BHF8YkzieeNpYozvhJLayQvV+ - sDDwe6IDn/hDXJtYSNSa0XHo79hVQafknZAfiMXBSS1LTsCSRkcSHvb3KHoe1s7GqNprbx+p/49T - MFHo2HOJ8/UIcCFM0VoB0LhQlzcj7vORQSNrDpVS3AKgdZPsJ8qpsjLTeEKszU8B/GPbBNVpAuv2 - i0YwAtkNN3nzOQE2Mq8mpj+SYS/iTSgJFs5q6VKN0mwf6nu+d96BteocdQrA27aSMXo11adLbReS - NEUkBjRL9/sNl6d4qGCXesp3DZym6pA1Zf7numhJmqVdFHy+XgmfSOZaSGHBDMpt6csHtBa11mmB - 1w4S6WN5e2jKiVq+30WFAgwDw+fEwKIgGyoBD/4khdTGj/2wC01WQJ4CG53Z8e5mATqpPjBJdNKY - Y1OfJXRZLKdbNvAu9MLzVlQlHmVZkadmierHaDStK5prpxlQHZrrcuWrRjZZhRd72EujVSVwEHP0 - hEYleON7I0LQlc7Dac812iw+Qzfaqk9AEe+0GR9xrjsc13bfLdplVK5g3mc8rJMPbK21L9c/5JUu - tEwMQNN00sbdhqaQ38tAqcGCc4CiQK7t68PnGxpiD6WqGng0v0bjpr4m7l4M0RGix44QFuMh8fOg - ysNxdgikEjwcIqwYvuXYJOJKvl/B3NrLRgSjc08HBYbBS9731ic5UGrMXMb489Soey7Z1K/d8paK - fQI01En3bxq9Uu/px1+W61ckFVxnuJ8SkM7Dgb9GQiG4msoB1y3SoKqpbq9Ny7ZETfIcneG5eeJ0 - e6IvIwKXbEamUBAK91p0FPrNF0/x0bea7i+9topmiVt3N5FweHRx/l/iqWUkXI2Q3UHkd8Gelp3g - 4TEs67qGeM+BwIgIuy5PLMu0ajDjSiVjgZ2BQsPYzwWVjWW9igInW1RSaV48qe4bsgRDhreUllkV - i0qNnwZ3fj3XURBPYdU4W+dKaD9F6LGF6OqxG/M5tR2scjOlyCB5K4qnh0VS83+UyavLndBt7W0E - 8n4aqrGdVwmnSqzRC2WLqxwhlkPkwWRWvuJRvdI+AcBdl+2EImV99JPQeNxJtsoYIeBDmYSXKwQu - OJSgU9W+y7dIlve7qXljjmVYqZ+n789KN1w7J6Y1BxQfQyM= - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=5-sixty-nine_alliance-reply.gpg - Content-Length: - - '1118' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:31 GMT - Etag: - - sha256:a37f717849486b9aee64abb4a643ddd68b1113b084b1877331662db5faf2d4b7 - Expires: - - Thu, 20 Jan 2022 11:11:31 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:01 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies/d5b658be-aabd-4d7b-89c1-51de7fa246a0/download - response: - body: - string: !!binary | - hQIMA0N7bDxphDAvAQ//TH6p5AOn1CrjxYM86z+RMEqJA3KAWtZRfG0DN+HrRi4U+4jqoRkNuScK - jGMANsbTgKVFe8ho6dS9Vx4YFxcAxrNSRnOAkKqCK6EzSMXQ9ndwhBGTfLQDsMM8UCQTHb05OSyn - MUxwFS90J+WcoeAXimrX++kseH2p5UQGxe1wDooQqSvDJtPuIjYCnpWaNvp72/z153ihGAZ/83Hh - vHC2huc43vtGLKNgYYH3ZualcGBoQVbCGSLxVukaouLC2sqh2gqhSinEUdf+A62p66QexT5SqYaB - AHt1FhOtUey+LKaMskLv3LZc6GVr6UEEsybveRMgMtYwLHIkrKYIB1NQde1W60nUEax9MwKA4ZqN - 1ArV78ssvbVzAFcqfvIuHlXfPXOmD7t8yuT96hTNAhe2Ih9fiYGVhHAbltP/d6lCzFEzvEve0BNj - xwH31OrmzsrGMKTD5xpjaQnJko8enAK9/V/s+SFevWJeGuzPUd7M3ymD4pGXzWAw03BGK2B0+YOZ - IpAoPKbh6Z8FlBL0tujL0PS77PM4s7kxKZ7pWAU2m/PTJv57GtBaw2t7GTpWdFNu+9zx2vygdQwe - SkJpaM7tgonvBvbwyqT2jYbzqCfRqj45AHntTzEw3UZlxLmUvHh+u/LLPvn7EDOPtl5UQANgj6Rl - XnTgw8k0znG3VRJ6vfGFAgwDw+fEwKIgGyoBD/9pw1xQzuUiV+uEuopup9unQa1XTkfL6X72Tqp5 - eCvRNOHHYmThZCp9QHnsJm2NBwHyZfrYgzl48quf86iekCoPgyW1RPTUEGDCJjK7XvtNULsMZB4m - sDzS32TgP5MKzxGmAwQWTj7o8s1QXv9gy2wr/GpVfF6mbHtWALY+fovm1TkQ8UGBv6j9LZcBjqn3 - MZfZnCqwOqa267ToB5AjxbL6X756TMaydpJ0MCHhh2JcGYEKzyp67BON2lqF3pYfaw/E5u+4N8pc - +H5N1E9T23xANWJhiydk+BE1I4moDVTR+iVn3SywDKFqO3VdblMVAEHS8ZS+sTSXi5KJw0k/+v5+ - Q9j6uKeMCSjCwGInby4AQnFhlKXL1hBaYFVAjHAaXZZhGrPZOErESOJAFCGW9WhJkedsi9HP0FUC - TuNZpJB31EDo34+LYIrfBmHXoefL1vwJKHSKR9KNROiEUT0hv6pK+psT3jXx/dCM1H3Ads6D6Rc5 - 1hcS1alsjXoWZJmgugON/U5WnMvDDWlKtgbHZQyelqEzcDvItemBqWNLqfrsDJ9wi4nQiEeih/xq - /uYB8dwYMhi1sW8R4Agn4hsQhchMtiu7sFqAm69KJR2c38x7njcZnym3mEn6KS11ttbv5Q1kBRLm - O8c7jLtVxyxdwUGIBsUfwFM+xQq3cGcZ6Dfdx9I+AbOZaVM3gHy0lp3wxwUiEVWuyRG/1/ys8jlG - Y7W8jTPskwLJRay6Z0wkCcGMYPKnvyIuMuv9gaU/FluEaAY= - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=6-sixty-nine_alliance-reply.gpg - Content-Length: - - '1118' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:31 GMT - Etag: - - sha256:506b499968c47ee42d2aa758cf2043499810091417f99d4bca76a2aa239d5b52 - Expires: - - Thu, 20 Jan 2022 11:11:31 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:01 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/92b1914a-1b1c-4674-baad-1fb662aed682/replies/f774fd7f-55ad-45a6-9a92-05053f9628bf/download - response: - body: - string: '-----BEGIN PGP MESSAGE----- - - - hQIMA0N7bDxphDAvARAAiG+s16Vbg4K5FlEW0uWcJo7kNeIpFZa01+NEF9IwW21j - - VVP8spdAh5z2tfAsEFHr5uQ/rT0PJT7EfKe41x64rYnsTH8daqdnv6TFzAhH+/zb - - SmyCt5uvPrlvUJF0xXpHjkolDn4zg6UTXKEoOsNfMObXgzmMFxIyJ8mRd7NcOlkB - - yiOT7Tda5ym8gJ3iSnqk2q9icoDsesHI/NvW3UOib0RXsK4w/9GK7LIh9C0ojV7U - - 41eoRjZuN4ed+B6A9URTN6e6QX9afeDh8vif0aGa/ToUGVd4ZhPYoYJrXcUQc7Q2 - - UCGt14QoTsOh8OMi3Re6Z+KKELy2FAdhbRccoGhK0w6ehajVniCDEt03/KqnBCEs - - BPhEiVpcHPrDqp1Il9mOp03l3DkZtlnmBqLG70KPz5SiEYy6GlXR29fNYrNyGwGY - - 2Kut6J8764T/2qKPYoQm24N7rMm/Liy7tfQC4GIEgAKFoFfvbbmES/WmgYIzpHy5 - - gscF2pPKUINDQYVSpkDo2lEvcqDzywo/Sv9GzV6uJmXFOHIc8sQbknzMnWiPJ0Nh - - Heky7XCzanCLyfHCkg69j2EAlVkSxPK/xIp4S4UtOMdhmzyTQc/ogRyLRMXZRm/a - - FkQFoJp1m5quMK4weBTwq+I+VwOP6OJXR9ia6fh8n9pu3TkcJQ7aXvIXgmmWq5GF - - AgwDw+fEwKIgGyoBEADdkW7iwa1Tu/b7WqipYFBtAfQQaiXf041NQrNy9KTZkaPQ - - xEfQxmrjVPlbt4lN7Ldsibz8Q5qKVvJOn6t/SF0nWKFF+MOGA1E+7JXDMg82c1gN - - dS56dFio+2GmmQjJc1kGn7Qpn4Q61n9jy598vkeoVJrXdeILW5eycFInkf824p0L - - i03Q6nU4rIAzMz8gVpZlGbzbT/3xsbpz0uhiPHVYUT2Ry2+W4q4/CQzo9oxG3/i4 - - kIZs09z8as7PHqgdwnnXe055d9/4phLfFsCACpDuktryvcFVppdBVcov69AzjW5N - - 7lhHuAdUnspPLw1qqLnWNFnWrwIblBzLRIW3hphRS4/Kwwxmrfo3LMEjJaHT4xWt - - zAkWnqoUtrMdl7xp1V38xabDNYKAckbGd+rx1ZfefslPgfttWqgakpGWLa/vixcS - - RUi38eFDQmefFtk9KZCUEl3bVd6leO9NG6TCpci1bL1oBH3/aXaktEst2rvMhx2h - - TUK31qUbX2SLXpR0OHIPgmjpN/KTt1zj+52s7GxiMAtpPt7GNQpRV4Zw5Ka+fBcV - - GiLkFrXPv4PLYGmvoESv20Y+eoYO0jS4QKVLeuoUmrHyHeV3SnN0rE67YnboUr7j - - 3N2wjAR/eiGM1i1uDousNkkyzrRGD+Dc2aZmpQFdckyPB8ZmnYb1DlN5McF5vtJT - - AZeUU5EJgP5oNSJHK5SmCTb7hjT4/C/Q11APLlS8ZRR0qwtuFHTFu222KMPNH9uf - - Dsw3HgSs3Cwo55lbButmAegxnnUiGE1/F1X6ar1p2MywymE= - - =Eo11 - - -----END PGP MESSAGE----- - - ' - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=7-sixty-nine_alliance-reply.gpg - Content-Length: - - '1605' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:31 GMT - Etag: - - sha256:ff5cc185ef0e96a571d94298f07b2046ff66788649d7548bed771f51a7ca7bf4 - Expires: - - Thu, 20 Jan 2022 11:11:31 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:11:08 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/replies/158dfd73-3cb3-4a6e-85b3-f37ae54e0802/download - response: - body: - string: !!binary | - hQIMAy2m2NzuNpRrAQ/9F+gtuJpPO37A/NM6OacHAK+lBUvHM8icpiAz35EqSbr4OnnAQ8IRX0MU - v8Z0QpNB7+MCWlWY4QL59zaBuqHwIeg6GAu/szkpRxhD5eKAvRa1ukR9XrQ3pDmpNHU7k0l3x+jI - tmKqt7WtxqiZ2GjIDTitpgowd40k3Af/BeYQ7IEHqzv0xbpsVp06+RtLFc05Tg2mVlK9lt5mJmht - VcZQJJ3P+d3wcROuKuwmPqzi5FAlLQx3opOy1hbukgpH4E+lBSA1EwsYZ91/4AgnhB+VLgw1EAsh - SSCtNfhTE5AAaJ/a78zf30ukkZ1v+mIaoX+MFYCk0/eGVQpuElK2OO3MH8lrOylr9/388cP+aWC/ - iN7RpXdUDWi1iUtLLieBwyVYTNnw7yea7Mbpme9gwjk0Jg56dgs+npUWLp+BTChxWAR67nG4M6Fz - vNZbclyvwyrojcBWKDnP5zIGIxGFufNeJcAehapP1SVuxuOO5aCwaKSZLiZZeINDhn7qJ4rNNhja - 2fwQbVmMW8WMh8m0ofijC1mQEj6bh0ElUzkZlRcD1WgfExnlyHov8AWu107IidLqalAU/rAGksd1 - CxxCUZ8cixPktyV6jE+g2IMGD9iNKuXmlJy20ITvVpaq5OHT8lUPJIMyoZCcfbNJy4ys5YASATH0 - aDU5C7iLg3hWltKCUU6FAgwDw+fEwKIgGyoBEADbIZ0faKpZjWxU8Pu6ZGNEphU3jYPg6CT1j3M7 - 0Sc0kBu3WZZDbAH3wUPbMCD4xNnTWhxjBCUmqLorPXXXm2LpE7FaApUS/DXl/TjTdYlKml+MsXph - AhdQQs/P6w/WhiHI92UAOdWnAtKebjMqh23oaFVVuVdkdXEdz62aSOqkE5PLJ4EggzaAEo9hwc3H - m/zq6f5bxS2BdgnEUuL+4Q3iOiydQ80obTJZNIRDPL6cmC+XKDrDA3sXluviOA3ct8nnwtwtkSGH - /cq81wt9lNVxpVriOZfFIe74bxJ3PQvxaLGpcqFg8nT57bfVzkhfPuXYh5AlNO459RUkiaZa3vmZ - ZlltTq5iNIrlTPqX6GerzOCHYYu3CT64DgviXF9isKgukzDyZmeGJK/LKSG+uC/CuBSzF1opE6SY - F9B0sUTTqPJ7mBmJU9wpoNnQG9uGx9/qEqRJ43k5KNGLUs8LwtqBhKkBNUA9HnasfjYdDvhmNxxk - ENr+Vg3IWqwsCrSeaOI7BaYiokDpympu44q5NZ1f/akfXjdcdO3Z7fStB3lOJX/ZvVRcZyg5fkXd - wSg5jQ3Nqyq1ZxTkuUt+QHx+74VMQXJ7e/w/OLrJNoedgLM4eY+U2PqhsdNY0qXQAU10eu/yoK20 - IWQoqBEDNvKbs8T0zTELQ8Rw3527ujnro1cfoNJtAfJ5dQ7MOzrxUSNXW38Y/O2idXYllsvRNodt - kahbwINUfi3i91KBHXq7wAdQ8wODMmyLXZ5tJCbnpkHrH9wx0/Q+W8omR2zjdOgD298MjO0f0wAR - 27+cdwdzVlNEWsvI2nIr4bWhIq/iEq0ZCw== - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=5-conjunctive_lavage-reply.gpg - Content-Length: - - '1165' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:31 GMT - Etag: - - sha256:6fc20abac42bbb6e36d08f16e84de997605c3caa88b1b6610cff5453f0a78bd2 - Expires: - - Thu, 20 Jan 2022 11:11:31 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:00 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/replies/24fbb6b4-504c-4fa7-9971-e6f2d1447a48/download - response: - body: - string: !!binary | - hQIMAy2m2NzuNpRrARAAv2fCgqOcLQn5BgYTSajwFM4sm++V+BFhV2RMZ0Ywc7yIGObndNc3H4v2 - 6CFo9OdMA2+uQrRzF3sNwoFn1tFLkRLZR4g2c0R8cynrB8XYgV2dR+T1/969ZEfOcCpFVOeAl8tD - Mld8VeC2HIiz7ttYMnRhO0LSuDEegI78z2idd/ugDgJa6oDCdtC1H4iFWiyES/arZQhlNBonZcJb - K9ujj6KWKysqB78+APhIUBF8DuAhRFv13raTqR+y5YZBJoGLqCt/K37Gkj9oV2Ty/juFBKKEZgiA - wEGgIYY5DmytKgErLRIZhKr/mfjeSpAgtMLFp3MLH6BXASzbGvUZoVmPcRcg0zujYARWu0cj4NFf - tfEHO2qqW0WQIUhzjEYvQEf9lbu4hZp9tNJ71hASCXJpVMJSkazq/5Xnh2ukFlSpvEaSOl1nX7jk - 7UMHQFd6ckTIssp7aIrZmBJB3kfcGxSWkCmu05fMFDr6LfxeyfJlt7kDv4PP0xHaY0A+aJ4Pce+s - WSlRkl6akI0+ZLsADxRNq1MwSVi9G9wqgoJ64CUJyjo9nMWZUyNISx7bYnZLG/0RzS57N6iXQkwf - pr9c08+zL360sJGnJOKSaAD05VCgduE+EbQ02fd/GN8sC7pJ7vc1bFoOssmIHjVtuJtCX1hxXuie - wzWk3g9HLU0Ge/P7wHiFAgwDw+fEwKIgGyoBEACzLkBPhzq0XbOkNrJ0mgsG6Te9AIHzZMmCpSJB - FBBaGUwkJP2njofVnMzUzGZEiloNlHU0JqU2h+OygDwKZWopcnAvjSf44nSXVLariWywWWtRrTUp - /qLymnpIEkK8LVrwGKwNhavEzg1xRM0FadGTGPOpHhm9WWU1cVU+zxy7JD/RJCqByXhZgwBnveK9 - 7o7/8MtANWmmEK/08zzfRKJAUDjReQFlbyTLtTzLhZ5qRapDPMHEc/5iE0FyArfUxmzgoC8abvuR - xXcE/rqj+jXpekfJGnh/b1KSa//3FU1KglcEN12aDT09hfYZLs5aNYLfhRGCsGUwI/sGhyr7fTEC - swj4DcYhbRdhcMn2LvaLLxHDzT/CYwniLzryFGN/yYFqoWH4VNK/k+fd63ovJoz2gvTOGtF85bKP - D/djVUB8ZHrwQPYhmVPAq9GgE83APidKDVpiV9o6CoGc8lNVnUNqMg1m8OQd70wxbSNQR1UscTsv - pafXWb8BGCv2Dh92nGgYDsVG4Q7kyxacH8/6b3Ej0NAxlmq7T4KEhtK4zWAxNW98fuXvU6x/xOed - GUyIJcC6LRy2nvHKpebo+x/m9c+z5kL2IkNszDrn6K+v6zRge5KjwB8ZVaQWviVOCO4XBevHyBM4 - QUTOhwvaKSO+Lfr/d6SUkFeXPW4DszXo4aPFPNKKAdRQneC2tRM/jHptBBJcUOh30yiyVZXtqyWJ - bUWisJsylbza/CcoxEe9YVWqq8LATiXuOiIovJw9Hl4PowDN/a/tzELxzkEvkSpliChiOETfCBtz - sUrPgThyINfRHpw1vW0URz4mXgArtxIVXf41HDU6Ks4Jk6dI2ZV9RIfHvP/D0pXi+cBES5kf - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=6-conjunctive_lavage-reply.gpg - Content-Length: - - '1194' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:31 GMT - Etag: - - sha256:3d7492dee4392a2c7180f236615ebd6c26d772529d502c5124258127ef40a391 - Expires: - - Thu, 20 Jan 2022 11:11:31 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:00 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/replies/1c2ff7fa-252a-426a-83e9-5840cf657739/download - response: - body: - string: !!binary | - hQIMAxGWEiPHDepYARAAu/TMRu3Ff5fRgQqO/E5Bv/94dfp2b5I+AyQ5+ejoEVp1xxS+IiQWM+Sn - YWnrgUSCRlPRZLzlgORkyg9hV+Hke6/ycie75w4z5C2yLMp4fS2/bsIsAfUpd4diUUjc/L++RWvw - GX91oQB9aFsEJxiD6LIb5DvXf4EeU34XmTGpTUNx2st1bcTvsw3ApzsW4isLgZipHKYekOnX8qvx - vpOjVjyWEeSdNNQg+hAgB9JK+vp4Ueykhyz5Xg6EaPbWciYV/pgP4kDa0yilHImH+eSABa/SKUar - ykt0ny6BbbyfvZJXCC16sHuCzmddXBuhoEm7Z9dn4cBbP/mWVbkw0aPTYEdTNYMi5pMdVvSWlLbt - u8A2wKiOCkzUkaguZjbsJVJPc+jm0XQuccVqTdQkUiXiKZWw/pFxgc0UgqiHF6cqO57xZS9I7OQs - yx2CrR20ITwb2rRUxsF5SiUvGN39aj/2ycIZ5PGZ3dweQHDOMo5kR47aOph2Ac2BztN/s3x7fqfJ - 8KVjxCW5xlv9yhl/lIr6CPgH+4NqJvxQu5M3zXVr3hTnoTnBoLX/g7w7oxEwAi43jI0FEzm2e2bn - W03ezM3b1P0uLeNx2nmqo2HDZPJPItU7BgN03A8GBmxPsDojeR0khzZtWPBPPxIyELg2I2gPvDo+ - hQI5s2Zwu3b1jYnq012FAgwDw+fEwKIgGyoBEADHptlGI/S5RTU8LAGF5COwuVWEIGieqkNRnIEi - +aq3ln+i9lDHpbUoqjtcxAGYaoC/AkmWwu8Zb08LPOw6yGj9Vq8HkvqYoF3PVfR44gr2g8MGBGhl - Y6NqAAXAe/SxqGJUsN22Ag9TDKWcMPxM/K5+7IqQixQy6FvqNrQ4EHwAJUxTZZH/8A9q0r7SWYtv - 65OSbkaIaO7ZNxzqvCP5f+Ut05BX7xpVlJ2JMxZFGZCy+s0/0uinhtPbUsL3XqFhYVVFFGlfMpSX - KZMNIo7I4e+NzMpm90gHQpfbCoR2zafhxgADsEaHi6LNrm+1kHbL/acPKctAXbFeWFrUbjceBYH7 - kVdEVMP5B2ycHD8ER3HRXAOD/UDHb0Udn7zHNXojsNFQ30A5PD15IbdyL10eGm5LaFndkxcQRonm - 7ALRJXXV6veXtE2glXCMmbtzIBycZpxipEG6T0046uBZs9XhQ27UoQ88d5ar0MsgoZkTK4WKQlUv - Sz78qafEIhiuqxSNT6NErjBmgxFCcMvu1OP5XgCMsSBYCIVB2VmbrFVv7mpH0apqc9doMmveYsAd - L20u7ejj82IipaNxJNvTcwuXpbWt5woSIgY/icD1v8ms7ugDbPxHgUpqDOUhC6PBtTq/so2bDxEA - peMxY5zLQgFxKFJW4pOa1104hg1TdZyClxU629JAAfXer+CmTbev26iQ375glBw+rNyWA9J+iX02 - nu/JwYp6Z/VLK8FY/5WWZicqRnG/4G96w6zHwkB5zD7rF44utw== - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=5-indecorous_creamery-reply.gpg - Content-Length: - - '1120' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:31 GMT - Etag: - - sha256:8ea8d0a16663cc9b7d4f2e196ecd9d675ffef7f0f9d6b51294cfbba8ec99eb33 - Expires: - - Thu, 20 Jan 2022 11:11:31 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:57 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/55fb95c1-cff3-430a-8c05-125c67c81a6a/replies/5f5707b7-ee1d-410f-94be-1ba8c1929264/download - response: - body: - string: !!binary | - hQIMAxGWEiPHDepYAQ//XWIBkXv/uh9NDRr86nlqZ2gJGssV96HBp10HVUbyyyEVcQkZ/evEOizB - 0gFUBwqBwuYAazPNgfgEVywXbAERoFR9Pul4AjVCkHqbrPOl62BSsKpLSAQIV7YP6AlJPiO3Pm0R - VeENWPAjmotBHfpjgVwiCkQeSyF8lCAveo7707ppJT2hCpxjJQhtt1WIyOQSE7dAaAnywUWbBkoB - HldRJiKQa1O8CsNm8ELPQaczYR41LZpPHZ+h1xLR15iGnXq630ZjDagxok3+aXqI20MemxYOvIc9 - nqxQLduSWS0HykifTX7wYcCGj0PCFqSSngNUaQTAjSQPOQjUurWV4T2/aT2ixT9waPaHut8jpQ6p - Lzc0Pe/C0+yB6YBJJxINovWHzGL0N7ZWuPVmkWgPWcOCPu5Cc3pn+cv5fuqoFuJs1/G1t6eIBfqI - BMw3FPbq1sa6QUPY6RDqpRE8+48cHpVHBHKl2wc1uL9WVUtZdFKAOz2bLu7CAnD1VmZvpszgq12/ - j5m2UwINjo4N78UbjClCMgbyzji2hM9q2B7qkTf5JFZtg3YbhNKgiJxDpTcYdMG92BQS3vYjxHiR - FzxGwbDuQofyqIhIVhlK/42NZUns3W6Sm+fkl03fR72xtBdGCdC6tGJn7lrys8B8JG/Dr3LsBqnr - A+KqQNu3Xr2ERHqrie+FAgwDw+fEwKIgGyoBD/4m3ypz6E9TqX/mm4Syc+KOtfb1XXWGlrI+YtxW - cZHPI+9iCA2XamMXFdYDYueb0CGB0bP5l1THXkYsN+kvuVzcdXZ2hY1U8tMhvU/UNirdau3Is2vJ - uOQ1cqvJHTkEXEZdTzZG66Q6ZjtQjr8OMH4XugC8TKIR0gq/xmxk+49fq3FT09d+bccvFJQil5SF - +OKqJQGVhKaUd3bF/ITS20psYNcR36QK/QDrCM1dp2s85wWe8j8cnVPscuJ0lbX0qey5tMUf74Yn - cT8qNeKhh+Z/6oOjBB+UtcN/c6okMAKbX0IoQjCskE/D6ldscXkYTx4wVp3CyzZMGwyh8sjDBPp2 - ilsccaHhybJkFx+qwx/R8AoLc9za7qlfU6BYvasGeY0LmU9DCsS+fMQjL/34rkq248h4mxee1rap - v9vipuGDkd8EJMZPkR6PDL8iIHW13xqDlTEAkhuD0fsFVxGxdXgUdvNrPHb3/X+c+BDCdP1OFO7S - 0SQOO7NijD9O3NhNuKBkW3FnCYHb6sbJ5XRsD6h4LbGe6KwH97xULC4jRVSIHssTl+Nozcv1Xml1 - 4AJbGtcpna3Fc3Arjjop8UNoDntuDfXEuRulX+Hckib/IrIGTqgoEHYCEd/RMhY0ZE2hT/7iQBaT - FMuOpyvlV+Mb6zjynz3qy63WKV/cIAT3LwrWOdJCAelNp8jPH79glm+vZoeaZwjztzVucJRxKxtN - CuvLf+ziRI9v1FiL5GT5LAPpr3jtZ+qi9j9rKKAtPKfINXiS/B7M - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=6-indecorous_creamery-reply.gpg - Content-Length: - - '1122' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:31 GMT - Etag: - - sha256:1342def77aa79e3babeb0b709cf3dce39e69a8e1e04ec0c6a41c8aca6a979600 - Expires: - - Thu, 20 Jan 2022 11:11:31 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:57 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/replies/9bb8030a-8561-4a03-85dc-e921bd6a891c/download - response: - body: - string: !!binary | - hQIMA8XplUsUkq4fAQ//dI3ZLYYvp5nURcYqnL+N6qkdzdZ8SV8zxGd6wI7Oc0pUQy6Ri/Ap4gVy - 0fQGy+gA6QI599dDmRA5IxNV2GJ7D1KGkwCw9149ZGx3s1Qk9xDLN1+2xr6wbC8WnO7aMb3XPnzK - hEOpX+GIxK+PShiwR0TedX/M1ZybM2YNxuJn14/yO3tbr9nhBSujuQkSitQ7xdccdYiO3laJNjD1 - h1/aSUPz5yz77as0ctRoSwjl1+JY9O0RhclEKF8T7lIBms+uZwZ9b5yfQIlaMHd7iGT4HdIUMPjn - QWn2JmJ51BEa5G1Gpu6wEu5xT3fl6Z3Il3T3ARY96z9Ps2sCQg5FrTJ7U+RRj7yt2Xw1PF13DNpm - Sd2y6Qhpu3lFkM8cIzI+4O5mYL9Qe+9vy6B83vCtDKUZ9jqcZuGa5HD6f4Gzcu0FW1WAbCT02MAY - YTM8p/tyAoEIKgKcQxFmEhMFbaPOQ20TRXKb+x5sJGh1i5M4CmMQsGvczZrh13Zm5QIw9cIqc4de - uh4WrMsSHlGpdR+glbzRq7kCoofi3QOSrsTGrnaIPqPp4M3VNNJnR47yipKLFSGMI4T6zqHSTelW - ClhS4svd0qSPVK+DWD+XJ5lHrUDIzBM7FyGEkWAQpbqHIaE2fAN9QloAkcTPSO3A3/MdnYKHFLPC - BT+m30B2N7D1S7HC5geFAgwDw+fEwKIgGyoBEADBNF5oX0O6LpdpJAYuZpoZkVbZ6ZK0uc9gTh5N - CaoJNS2gHZtwhzqfgFzZVu9hERuUFvELXaeebv8zxNSRohUtIr0uDOWA9ZFJ+IrzaSBEfns28jkX - b8GsGeJQ3FPnvdp0LtOGAsrUGj02e71lJOx8qCfVgo1d4ZKxHpCSdC9+CoZbCxPE6a4TRCiE3Khu - /DDi96t2C5jNRHCIsfgwbaBB7sLeibkiIMhiKYGMz994UmA82XAHPdkIgXUsgju1UwxKfxk84Kwe - F1hybOfkpjAJ7kH/E5l5Udy7eEk5kz1M9TWr2UHSpY48x/enEOWYoAcC7f3tBKWak3WrxOhCjPjk - /7y1vSMKCLnsVkdNAJ6DTMpjQsv5aKuk8UPMTqw5oEl7JuFKcwdztXOgtsVXbe8t0rYTLMJlDa7w - 5Q5erJ5PdkQexpccw68Xswa85GZSUCIwqywrW4v5T3oemN8ZdZWuACFLBPvv6/JeRg+wEN4lk7qk - 7Q9FnjbY8a2Wn6ydCh81gAm6XQn5s+HH5FEVrJBbVrshDXZgdFIfLer2yyVOBOi8HnzYylxBgOHH - IRRlW5zV3c8bcPsX4doyiHXg6Rq8xs0vJRghqVRJXLYzsp2KG9h8gUvvX4F6I1o3zTE9RRI7jUVQ - sg81ViU4toOfaLcKuwpXKfy8tZR37+FZqWQSy9JSAdJ2DdIiaFHAX636/MO3AYocVMKsfQHHMmES - zPxveAOVrYp9wctgh3dNe7tJqFJZgObxmyKWdeLTmC3LE0P9d73Py9yfqmlZ8ADishAQToTzkQ== - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=5-concrete_limerick-reply.gpg - Content-Length: - - '1138' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:31 GMT - Etag: - - sha256:be7131a49df1b7a26d0610a96294198e1b27d7f13c18fc7b420132e9604e878a - Expires: - - Thu, 20 Jan 2022 11:11:31 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:51 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/ae59153b-0871-411a-a72a-0f4c41a76ee0/replies/0a82f046-581c-49ef-9b51-ce5b73e45c1a/download - response: - body: - string: !!binary | - hQIMA8XplUsUkq4fAQ/9HcK9M4c7Tks2GRPrAJgP7c3FGgz8Q/2HPBNoc73Fu1vsFUy19Zk2UfKX - 5LpKqFvMvo9T+HZPscKkoYpru68WahEAyIvdWRXl1OP072usBa/pOel4MdsX0l+ShrjK5H860zp3 - shnbNAhmpeEJ2TNQmDNj6UQsJWTS6hMoxAWIxBbuScqUk5T9oNEL7BSxZQnBfsMt50EPf3F4Fcn4 - aFRwWZtQZYlJjTodr1QiPykSaN88+ipqB2WatT+zxwBDVhjZTDWLZeprizvV+Ezxk4HwkGVm4C3C - lGquJCjAKt6t392zDVd1jEy83ctiu9DFZ/RBuVt6ath47JpXXKYu9Pm+hwYOZ5jOlE1C6z+B4xWd - sEDpocvIUxt+8VZx7DGACGRzHbJ5NapObt2eX6sQgxyMOwmg+bYqo7DHfbyMdPLY4SE+mytI0/Z2 - mm3/6yOOnAEOl3+5/M7aUPH3qUy/4S63iJKQ2banBSD0yDNQ6I/0MnU31AysERrRCSdxOExq/9u0 - IqHhb0In7hX+6EM3mQSg+z0AvX/xHWcn24TeSjMv/9WMFcasm85Xb305FVFrRyeMPUDcrbwepp8G - J/pj7mldMCe+5I17pxnQ8sImFt/GZG8DqoVrR6K2s5s2DCKywizUjifHg6L1sM8gY8d80y50U6mR - Tr8WNtdIdVuANcufU26FAgwDw+fEwKIgGyoBD/9+mmWhGDd48AshmcJ2SiqkgYuYUdp10ujWVZNx - IN2o5monN2AXkTyLUH6h0f/5HtJEGkoqXzQUs/DysOIRu27QqMS4BjW3fWXfqcKlBXItYHdd+BBw - czdqXrEMxdFv4MiP8q796+keQsJizPInpyApvFz4j7n9oLyshNLU2z+QoDkhKir6q+kSoDkuySug - JS0qzkdP0zp1QF/IzmmdyOLbApIZpYCY/wJMxVrqeBijl6cwHV5O+PMw0415WRxNXZ6PzEGzMeX0 - zSgputz0Jx4f7wpRjS/jgcP66VHTAl0dAKtEY7FHPUS68/0tBhsLOYGv8AJA4evAeVPCWhj4zJH9 - dpTTJd8PDOapoQH/xBEvt6AN2WKXeDH52tl0QFdtmVDPYjbqo5zh/qctHKv0QdsDjZZXmpnTCrfq - nnLRagcPeW6YKyn8yhrP44VR6Gzt9CSN3HGPmjfy72vqnyB0rEdkYoSEZZ0hxTsZ3QMT0bZ7sDPA - XK19LW9BRzjZtlKSFGONuciDN5lR4tQntGacjMcOj/xGe65PmuL484mak/900Cx9jwrw1hdq+a9e - gpKDsc4KG9suXkiJrzEHQE+18kgRBvoMZTAbumECKOuHUgZ919F1GgV3No6XjQZ+botyN4mgSwJm - VIV18ep7w0SQF8Qb+BCo8mbS64+nXd4cQfwtktLAIwHCxqT2yTvD2UXrLQXoCIvFP8xJ6T92oCgn - sSzyBciKz7C4EQ6N9dKQSo2ZXHSRO81/LuBGhreMQnhYiV90OceTFJ+U0nFWh7smggqjZSlqflg/ - W5wcqd945LAnGlQPky0AQcOYl5cFa2cHE6FZNhs/hQL5CAIir9AosMeOz7A+msaijWWsnkfc8KAF - HIrk8/qi7WDKd3ni++4dUBP9+xWijpy6jHzD3DJgP30sXFCDAjlvz+4Qopz4wXTncY03ypkcEGjP - sGsGWkGeBwyOvdxwk02XXTWyFv6aFenv6dNoJ/Mv - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=6-concrete_limerick-reply.gpg - Content-Length: - - '1284' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:31 GMT - Etag: - - sha256:df33b47b1b077cad3b8ab00a5eecef38faf353be83387ca4ddafe193a8ee81f6 - Expires: - - Thu, 20 Jan 2022 11:11:31 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:08:51 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token eyJhbGciOiJIUzI1NiIsImlhdCI6MTY0MjYzMzg4OSwiZXhwIjoxNjQyNjYyNjg5fQ.eyJpZCI6MX0.zqNMPMXnh-6eoI9z9T08DKaCcvAoqVz0PliZ_0nkAKQ - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.26.0 - method: GET - uri: http://localhost:8081/api/v1/sources/50c5fa95-eb69-49b6-8599-62b12cff7d7d/submissions/2281fccc-4cae-4228-a837-e6f3a3e1e6d2/download - response: - body: - string: !!binary | - hQIMA8PnxMCiIBsqAQ//VfnuIjbnRUrH1WRMvSak2SMigZymPdL6hvNluiuGz4hYbNIZqKWVjuzy - 3BNnWhvWpljKFy86NsonbdF29kuOIPePWLdXVe8mL4a3Kc3IY8T5JBWsvnkSl3TEaRGrlWsG5/ag - 4NkyBH45p070Rr57RqVcUBGe/ckzVhuiIOzmj3ujImMGG+ozo2kWPY2RfovqDtocUzywbh4fxtRD - lZQ5lgercImj8uvOaR0vbGzl67zg8HN4tz9U7QMxd37M2+PEBQoNILaRx2OQwyXEAjP89zEbqQmB - +N+I8WcHfvnj5V95JQ9DJP3LjOBYDb9fcesY5mu7E3yDzrd7OJkUhAimik7ImjkeVTnJx3IkNiRp - GutO8DunsgomolaehXlZrJ5dRU/SIISKcEPZlXc4sXpls+zS0S6d0hhwF8sgOKmxv55hWWe0+2Nu - nkXNUR3rxxKYyYf4Pv2VPJVxnr9+4u0MAAV7q3ztemLJNSAS8T2eRX3pkhKo3tRfDLvovSpqCIqT - ZMTSODjs+whuLDoR8DZuW+rGllZDu9OZO2V+UnODrH8ilbZ3wxt6Ryo6MR7wZbocbrMYNewtJFML - SS7I9xVzHmLDSfRePHo+kXa2qsD2nH7TQJ2H9VIyA21SvHVtDuqTjiZPSuypsuHldnpJbnrGQtX3 - CChqw5bh+aBLR5K8t1TShAGS5bRN7WaLcnaEqZfWFHTduPGNEOtpHZtVnxWrI/Khxwlm/HDmmuRV - I+CC5eQeIv1dQ889/JZNOq8z8EuofNes2mnw+fkEWdyFfllb55HBxwrtRYphlujUDTVy82+FfY2a - ozhTgY58FyjhaY3t8Y48vMHJ8j4BfsXkTHGGXGDPuLBg+Q== - headers: - Cache-Control: - - public, max-age=43200 - Content-Disposition: - - attachment; filename=3-conjunctive_lavage-doc.gz.gpg - Content-Length: - - '661' - Content-Type: - - application/pgp-encrypted - Date: - - Wed, 19 Jan 2022 23:11:32 GMT - Etag: - - sha256:1ae2759fd28879da3d3ba964ce8dfc13280583a08219127997508118eed6b4a5 - Expires: - - Thu, 20 Jan 2022 11:11:32 GMT - Last-Modified: - - Wed, 19 Jan 2022 23:09:00 GMT - Server: - - Werkzeug/0.16.0 Python/3.8.10 - status: - code: 200 - message: OK -version: 1 diff --git a/client/tests/functional/cassettes/test_export_wizard_device_already_unlocked.yaml b/client/tests/functional/cassettes/test_export_wizard_device_already_unlocked.yaml deleted file mode 100644 index d59c25ebb..000000000 --- a/client/tests/functional/cassettes/test_export_wizard_device_already_unlocked.yaml +++ /dev/null @@ -1,1518 +0,0 @@ -interactions: -- request: - body: '{"username": "journalist", "passphrase": "correct horse battery staple - profanity oil chewy", "one_time_code": "123456"}' - headers: - Accept: - - '*/*' - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '119' - User-Agent: - - python-requests/2.31.0 - method: POST - uri: http://localhost:8081/api/v1/token - response: - body: - string: '{"expiration":"2023-12-08T21:31:36.503560Z","journalist_first_name":null,"journalist_last_name":null,"journalist_uuid":"c63874d0-0723-475e-8773-a5a0eeaaa4f9","token":"IjkwQVJGa05CWDRQd3hwZVBWVTZfakI5Y3RxRy1JeWZNa3g2MkRGNmNlX2ci.ZXNvGA.4vDAGIjsM4zouaM3IhIBR3jzIrM"} - - ' - headers: - Connection: - - close - Content-Length: - - '265' - Content-Type: - - application/json - Date: - - Fri, 08 Dec 2023 19:31:36 GMT - Server: - - Werkzeug/2.2.3 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token IjkwQVJGa05CWDRQd3hwZVBWVTZfakI5Y3RxRy1JeWZNa3g2MkRGNmNlX2ci.ZXNvGA.4vDAGIjsM4zouaM3IhIBR3jzIrM - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.31.0 - method: GET - uri: http://localhost:8081/api/v1/users - response: - body: - string: '{"users":[{"first_name":null,"last_name":null,"username":"journalist","uuid":"c63874d0-0723-475e-8773-a5a0eeaaa4f9"},{"first_name":null,"last_name":null,"username":"dellsberg","uuid":"ac647c21-82f5-4d19-8350-6657a7d32f6b"},{"first_name":null,"last_name":null,"username":"deleted","uuid":"200a587e-b40c-48eb-b18a-0d1263f8af2e"}]} - - ' - headers: - Connection: - - close - Content-Length: - - '329' - Content-Type: - - application/json - Date: - - Fri, 08 Dec 2023 19:31:36 GMT - Server: - - Werkzeug/2.2.3 Python/3.8.10 - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Authorization: - - Token IjkwQVJGa05CWDRQd3hwZVBWVTZfakI5Y3RxRy1JeWZNa3g2MkRGNmNlX2ci.ZXNvGA.4vDAGIjsM4zouaM3IhIBR3jzIrM - Connection: - - keep-alive - Content-Type: - - application/json - User-Agent: - - python-requests/2.31.0 - method: GET - uri: http://localhost:8081/api/v1/sources - response: - body: - string: '{"sources":[{"add_star_url":"/api/v1/sources/1924d581-a3af-45c6-a3c9-0ec2f1205bc1/add_star","interaction_count":6,"is_flagged":false,"is_starred":false,"journalist_designation":"oriental - hutch","key":{"fingerprint":"DF4DC2E19F0A6A304C8C3188AEF8C5E2BD8AE199","public":"-----BEGIN - PGP PUBLIC KEY BLOCK-----\nComment: DF4D C2E1 9F0A 6A30 4C8C 3188 AEF8 C5E2 - BD8A E199\nComment: Source Key None: - self.stdin = mocker.MagicMock() - - def communicate(self, *nargs, **kwargs) -> None: - raise TimeoutExpired(["mock"], 123) - - api = API("mock", "mock", "mock", "mock", proxy=True) - mocker.patch("securedrop_client.sdk.Popen", MockedPopen) - - with pytest.raises(RequestTimeoutError): - api.authenticate() - - -def test_download_reply_timeout(mocker): - class MockedPopen: - def __init__(self, *nargs, **kwargs) -> None: - self.stdin = mocker.MagicMock() - - def communicate(self, *nargs, **kwargs) -> None: - raise TimeoutExpired(["mock"], 123) - - api = API("mock", "mock", "mock", "mock", proxy=True) - mocker.patch("securedrop_client.sdk.Popen", MockedPopen) - with pytest.raises(RequestTimeoutError): - r = Reply(uuid="humanproblem", filename="secret.txt") - api.download_reply(r) - - -def test_download_submission_timeout(mocker): - class MockedPopen: - def __init__(self, *nargs, **kwargs) -> None: - self.stdin = mocker.MagicMock() - - def communicate(self, *nargs, **kwargs) -> None: - raise TimeoutExpired(["mock"], 123) - - api = API("mock", "mock", "mock", "mock", proxy=True) - mocker.patch("securedrop_client.sdk.Popen", MockedPopen) - with pytest.raises(RequestTimeoutError): - s = Submission(uuid="climateproblem") - api.download_submission(s) - - -def test_download_get_sources_error_request_timeout(mocker): - api = API("mock", "mock", "mock", "mock", True) - mocker.patch( - "securedrop_client.sdk.json_query", - return_value=( - json.dumps( - { - "body": json.dumps({"error": "wah"}), - "status": http.HTTPStatus.GATEWAY_TIMEOUT, - "headers": "foo", - } - ) - ), - ) - with pytest.raises(RequestTimeoutError): - api.get_sources() - - -def test_filename_key_not_in_download_response(mocker): - api = API("mock", "mock", "mock", "mock", True) - s = Submission(uuid="foobar") - mocker.patch( - "securedrop_client.sdk.json_query", - return_value=( - json.dumps({"body": json.dumps({"error": "wah"}), "status": 200, "headers": "foo"}) - ), - ) - with pytest.raises(BaseError): - api.download_submission(s) diff --git a/client/tests/sdk/test_shared.py b/client/tests/sdk/test_shared.py index c1f7a5a88..9793e381b 100644 --- a/client/tests/sdk/test_shared.py +++ b/client/tests/sdk/test_shared.py @@ -1,5 +1,6 @@ import datetime import os +import time import pytest @@ -10,9 +11,9 @@ class TestShared: """ - Base class for test code that is shared by the API and API proxy tests. - Tests in this file should not be prefixed with test_; they are called - only from subclasses. + Base class for tests against the SDK. Methods in this file should not be + prefixed with `test_`; they are run only from subclasses that define their + own `test_` methods to be picked up by pytest. """ # ---------------- AUTH VALIDATION ---------------- @@ -37,11 +38,20 @@ def delete_conversation(self): self.api.delete_conversation(s.uuid) - submissions = self.api.get_submissions(s) - assert 0 == len(submissions) - - replies = self.api.get_replies_from_source(s) - assert 0 == len(replies) + attempts = 3 + while attempts >= 0: # Deletion is both non-blocking and slow. + attempts = attempts - 1 + try: + submissions = self.api.get_submissions(s) + assert 0 == len(submissions) + + replies = self.api.get_replies_from_source(s) + assert 0 == len(replies) + except AssertionError: + if attempts == 0: + raise + else: + time.sleep(5) def delete_source(self, from_string=False): number_of_sources_before = len(self.api.get_sources()) @@ -98,9 +108,19 @@ def delete_submission(self, from_string=False): else: subs = self.api.get_all_submissions() assert self.api.delete_submission(subs[0]) - new_subs = self.api.get_all_submissions() - # We now should have 1 less submission - assert len(new_subs) == number_of_submissions_before - 1 + + attempts = 3 + while attempts >= 0: # Deletion is both non-blocking and slow. + attempts = attempts - 1 + try: + new_subs = self.api.get_all_submissions() + # We now should have 1 less submission + assert len(new_subs) == number_of_submissions_before - 1 + except: # noqa: E722 + if attempts == 0: + raise + else: + time.sleep(5) # Let us make sure that sub[0] is not there for s in new_subs: diff --git a/client/tests/sdk/utils.py b/client/tests/sdk/utils.py index b10af3caf..0d70563de 100644 --- a/client/tests/sdk/utils.py +++ b/client/tests/sdk/utils.py @@ -1,109 +1,94 @@ -import json -import os -from collections import OrderedDict -from unittest.mock import MagicMock, patch - -from securedrop_client.sdk import json_query - -# We are making calls to securedrop.Proxy qrexec service -# in the QubesOS to get the data from the server. This is difficult to test -# unless we have an easy way to store/cache each function call and returned -# result. In this file we have a new decorator called `qrexec_datasaver`. -# This decorator checks for each json_query call and related arguments sent -# to the function, and then stores the result in a json file if required. -# From the next time, for the same signature, it will serve the result from the -# stored cache and will enable us to write unittests which can run without a -# real server. -# The result files will be stored in data/function_name.json files. - -RES = {} -CALLNUMBER = 0 - - -real_json_query = json_query - - -# This function obtains a JSON query result from the cache object (RES), or -# otherwise performs a real query. -def mocked_json_query(*args, **kwargs): - global CALLNUMBER - global RES - CALLNUMBER += 1 - arguments = tuple(args) - # Now remove the one time code - # As it will be a different value every time. - python_args = json.loads(args[1]) - - try: - value_str = python_args["body"] - value = json.loads(value_str) - del value["one_time_code"] - python_args["body"] = json.dumps(value, sort_keys=True) - except Exception: - pass # Means no body in the call - - # Now remove the authorization token from the key - # Because in differnet runs, the token would be different - # that is why we have to remove that. - try: - value = python_args["headers"] - del value["Authorization"] - python_args["headers"] = json.dumps(value, sort_keys=True) - except Exception: - pass # Means no Authorization token in the call - - # Make sure the body is also sorted - # This will work incase one_time_code is still missing - # and there is a body in the call. - try: - value_str = python_args["body"] - value = json.loads(value_str) - dkeys = list(value.keys()) - dkeys.sort() - print("\nDKEYS: ", dkeys) - print("\n") - od = OrderedDict() - for k in dkeys: - od[k] = value[k] - python_args["body"] = json.dumps(od) - except Exception: - pass - - newargs = json.dumps(python_args, sort_keys=True) - arguments = (newargs,) - - key = arguments[0] + "+" + str(CALLNUMBER) - print("\nKEY: {}".format(key)) - answer = RES.get(key, None) - if not answer: - # Means it is not in cache. - # So, execute the real function and store in cache - answer = real_json_query(*args) - RES[key] = answer - return answer - - -def qrexec_datasaver(func): - "This is the decorator to save qrexec call data" - - def wrapper(self, *args, **kwargs): - global CALLNUMBER - global RES - # This is the filename to store the results - filename = os.path.join("tests/sdk/data", func.__name__ + ".json") - - if os.path.exists(filename): - with open(filename) as fobj: - RES = json.load(fobj) - mock = MagicMock() - mock.side_effect = mocked_json_query - with patch("securedrop_client.sdk.json_query", mock): - result = func(self, *args, **kwargs) - - if not os.path.exists(filename): - with open(filename, "w") as fobj: - json.dump(RES, fobj) - CALLNUMBER = 0 - return result - - return wrapper +from typing import Dict, Optional, Union +from unittest.mock import patch + +import vcr +from vcr.request import Request + +from securedrop_client.sdk import API, JSONResponse, StreamedResponse + +VCR = vcr.VCR(cassette_library_dir="tests/sdk/data/") + + +class Cassette(vcr.cassette.Cassette): + """Subclass `Cassette` to be able to handle two or more identical requests + with different responses at different positions in the cassette. Thanks to + @vickyliin for suggesting this workaround for kevin1024/vcrpy#753.""" + + def append_and_play(self, request, response) -> None: + prev_len_data = len(self.data) + super().append(request, response) + is_appended = len(self.data) == prev_len_data + 1 + if is_appended: + self.play_counts[prev_len_data] += 1 + + def _load(self) -> None: + super()._load() + self.append = self.append_and_play + self._load = None + + +class VCRAPI(API): + """Subclass `API` so that `_send_json_request()` is instrumented to record + and replay VCR.py cassettes. + """ + + def _send_json_request( + self, + method: str, + path_query: str, + stream: bool = False, + body: Optional[str] = None, + headers: Optional[Dict[str, str]] = None, + timeout: Optional[int] = None, + ) -> Union[StreamedResponse, JSONResponse]: + """If the cassette contains a VCR.py `Request` object corresponding to + this request, play back the response. If it's an exception, raise it to + be handled by the caller. + + Otherwise, make the request normally and record the response. If it's + an exception, record it anyway, then raise it to be handled by the + caller. + """ + + request = Request(method, path_query, body, headers) + + # Playback mode: + try: + response = self._cassette.play_response(request) + if isinstance(response, Exception): + raise response + + return response + + # Request not in cassette; recording mode: + except vcr.errors.UnhandledHTTPRequestError: + try: + response = super()._send_json_request( + method, path_query, stream, body, headers, timeout + ) + self._cassette.append(request, response) + return response + + except Exception as exc: + self._cassette.append(request, exc) + raise + + @staticmethod + def use_cassette(func): + """The decorated function `func` will be run with its corresponding + cassette patched into place. + """ + + def wrapper(self, *args, **kwargs): + # We have to specify an explicit path for each cassette because + # we're not using vcr.use_cassette() directly as a decorator. + context = VCR.use_cassette(f"{func.__name__}.yml") + + # Override `Cassette` to use our subclass before we enter the + # context manager. + context.cls = Cassette + with context as cassette: + with patch.object(VCRAPI, "_cassette", cassette, create=True): + return func(self, *args, **kwargs) + + return wrapper diff --git a/debian/control b/debian/control index b0c1df713..3416c9247 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: securedrop-client Section: unknown Priority: optional Maintainer: SecureDrop Team -Build-Depends: debhelper-compat (= 11), dh-apparmor, python3-virtualenv +Build-Depends: debhelper-compat (= 11), dh-apparmor, python3-virtualenv, libssl-dev, pkg-config, libclang-dev, qubesdb-dev Standards-Version: 3.9.8 Homepage: https://github.com/freedomofpress/securedrop-client X-Python3-Version: >= 3.5 @@ -34,8 +34,8 @@ Description: Python module and qrexec service to store logs for SecureDrop Works SecureDrop Workstation project in Qubes. Package: securedrop-proxy -Architecture: all -Depends: ${python3:Depends}, ${misc:Depends}, libyaml-0-2 +Architecture: any +Depends: ${misc:Depends}, ${shlibs:Depends} Description: This is securedrop Qubes proxy service This package provides the network proxy on Qubes to talk to the SecureDrop server. diff --git a/debian/rules b/debian/rules index c990004ab..acb89b646 100755 --- a/debian/rules +++ b/debian/rules @@ -7,7 +7,7 @@ override_dh_auto_install: bash ./debian/setup-venv.sh client bash ./debian/setup-venv.sh export bash ./debian/setup-venv.sh log - bash ./debian/setup-venv.sh proxy + cargo build --release --locked --features qubesdb dh_auto_install dh_apparmor --profile-name=usr.bin.securedrop-client -psecuredrop-client diff --git a/debian/securedrop-proxy.install b/debian/securedrop-proxy.install index e598af1a1..ffd45a19e 100644 --- a/debian/securedrop-proxy.install +++ b/debian/securedrop-proxy.install @@ -1 +1,2 @@ proxy/qubes/securedrop.Proxy etc/qubes-rpc/ +target/release/securedrop-proxy usr/bin/ diff --git a/debian/securedrop-proxy.links b/debian/securedrop-proxy.links deleted file mode 100644 index abddf108f..000000000 --- a/debian/securedrop-proxy.links +++ /dev/null @@ -1 +0,0 @@ -opt/venvs/securedrop-proxy/bin/sd-proxy usr/bin/sd-proxy diff --git a/proxy/Cargo.toml b/proxy/Cargo.toml index e53e6e48a..45461e854 100644 --- a/proxy/Cargo.toml +++ b/proxy/Cargo.toml @@ -5,4 +5,17 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +qubesdb = [] + [dependencies] +anyhow = {version = "1.0.75"} +futures-util = "0.3.30" +reqwest = {version = "0.11.20", features = ["gzip", "stream"]} +serde = {version = "1.0.188", features = ["derive"]} +serde_json = "1.0.107" +tokio = {version = "1.0", features = ["macros", "rt"]} +url = "2.4.1" + +[build-dependencies] +bindgen = "0.69.4" diff --git a/proxy/Makefile b/proxy/Makefile index 468fe6d8d..f3ead7dc9 100644 --- a/proxy/Makefile +++ b/proxy/Makefile @@ -3,35 +3,19 @@ .PHONY: all all: help -.PHONY: lint -lint: mypy ## Run flake8 and mypy - @poetry run flake8 securedrop_proxy tests +.PHONY: build +build: # Build Rust binary + cargo build -.PHONY: mypy -mypy: ## Run mypy static type checker - @poetry run mypy --ignore-missing-imports securedrop_proxy +.PHONY: lint +lint: ## Nothing (Rust code is linted from the root) .PHONY: test -test: clean .coverage ## Runs tests with coverage - -.coverage: - @poetry run coverage run --source securedrop_proxy -m unittest - -.PHONY: browse-coverage -browse-coverage: .coverage ## Generates and opens HTML coverage report - @poetry run coverage html - @xdg-open htmlcov/index.html 2>/dev/null || open htmlcov/index.html 2>/dev/null +test: build ## Runs tests with pytest + @poetry run pytest .PHONY: check -check: clean lint test mypy ## Runs all tests and code checkers - -.PHONY: clean -clean: ## Clean the workspace of generated resources - @rm -rf .mypy_cache build dist *.egg-info .coverage .eggs docs/_build .pytest_cache lib htmlcov .cache && \ - find . \( -name '*.py[co]' -o -name dropin.cache \) -delete && \ - find . \( -name '*.bak' -o -name dropin.cache \) -delete && \ - find . \( -name '*.tgz' -o -name dropin.cache \) -delete && \ - find . -name __pycache__ -print0 | xargs -0 rm -rf +check: lint test ## Runs all tests and code checkers # Explanation of the below shell command should it ever break. # 1. Set the field separator to ": ##" and any make targets that might appear between : and ## diff --git a/proxy/README.md b/proxy/README.md index afec296b6..ae293ed44 100644 --- a/proxy/README.md +++ b/proxy/README.md @@ -1,4 +1,5 @@ ## securedrop workstation proxy + `securedrop-proxy` is part of the [SecureDrop Workstation](https://github.com/freedomofpress/securedrop-workstation) project. @@ -13,21 +14,74 @@ rest of the Securedrop Workstation project. However, it is ready to be poked at and demonstrated. Feel free to explore and contribute! You'll need a machine running [Qubes OS](https://qubes-os.org). -### How It Works +## Security Properties + +### Isolation + +The SecureDrop Client/SDK can talk only to the proxy. The proxy talks only to +the (onion) origin it's configured with. + +**Mitigates against:** A compromised Client/VM tries to contact or exfiltrate +data to an arbitrary origin. + +### Sanitization + +The SDK talks JSON. The proxy translates JSON to HTTP and back again. (In v3, it +will just construct a sanitized HTTP request and do the same for the response.) + +**Mitigates against:** A compromised Client/VM constructs a malicious HTTP +request. (The server returning a malicious HTTP response is already game over.) + +## How It Works + +```mermaid +sequenceDiagram + +participant c as securedrop-client +participant sdk as securedrop-sdk +participant p as securedrop-proxy +participant w as sd-whonix +participant server as SecureDrop + +c ->> sdk: job +activate sdk +sdk -->> p: JSON over qrexec +activate p +p -->> w: HTTP +w -->> server: HTTP over Tor + +server -->> w: HTTP over Tor +w -->> p: HTTP + +alt stream: false +p -->> sdk: JSON over qrexec +sdk ->> c: response +else stream: true +p -->> sdk: HTTP over qrexec +sdk ->> c: stream +else error +p ->> sdk: JSON over qrexec +sdk ->> c: error +end + +deactivate p +deactivate sdk +``` -The proxy works by reading a JSON object from STDIN, generating an -HTTP request from that JSON, making that request against the remote -server, then writing a JSON object which represents the remote -server's response to STDOUT. For discussion about the shape of the -request and response objects, see +The proxy works by reading a JSON object from the standard input, generating an +HTTP request from that JSON, making that request against the remote server, and +then either (a) writing to the standard output a JSON object which represents +the remote server's response or (b) streaming the response directly to the +standard output. For discussion about the shape of the request and response +objects, see https://github.com/freedomofpress/securedrop-workstation/issues/107. -#### Quick Start +## Quick Start 1. [Install Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer) 2. Run `make test` to verify the installation -#### Managing Dependencies +## Managing Dependencies We use Poetry to manage dependencies for this project. @@ -70,34 +124,29 @@ PR in this repository. 7. Add a detached signature (with the release key) for the source tarball. 8. Submit the source tarball and signature via PR into this [repository](https://github.com/freedomofpress/securedrop-debian-packaging). This tarball will be used by the package builder. -#### Configuration +## Configuration -The proxy script must be run with the path to its configuration file -as its first argument. This repo includes an example configuration -file, at `config-example.yaml`. Configuration consists of the -following values: +In development, the proxy should be run with the `SD_PROXY_ORIGIN` environment +variable set, like: -- `host` - The hostname of the remote server. Must be set. -- `port` - The port the request should be sent to. Must be set. -- `scheme` - `http` or `https`. Must be set. -- `dev` - A boolean, where `True` indicates we're running in development mode, any other value (or not set) indicates we're running in production. See below for what that means. -- `target_vm` - The name of the VM we should `qvm-move` non-JSON responses to. Must be set if dev is not True. +```sh-session +$ export SD_PROXY_ORIGIN=http://${JOURNALIST_INTERFACE}.onion +``` -#### dev vs prod +In a production build with the `qubesdb` feature, the same value is expected in +the Qubes feature `vm-config.SD_PROXY_ORIGIN`, exposed in QubesDB at +`/vm-config/SD_PROXY_ORIGIN`. Yo can simulate this, including on Qubes 4.1, +with: -Configuration includes a "dev" attribute. At this point, the only -difference between dev and production modes is how non-JSON responses -are handled. In prod mode, the content is saved to a local file, then -moved (via `qvm-move`) to the VM indicated by `target_vm`. In dev -mode, the file is not moved off the VM, but is saved as a temporary -file in `/tmp`. In both cases, the response written to STDOUT includes -the name of the new file. +```sh-session +[user@dom0 ~] qubesdb-write sd-proxy -c write /vm-config/SD_PROXY_ORIGIN $JOURNALIST_INTERFACE +``` -#### Tests +## Tests Unit tests can be run with `make test`. -#### Example Commands +## Example Commands The following commands can be used to demonstrate the proxy. @@ -118,7 +167,7 @@ JSON. The proxy detects the malformed request, and prints an error message. $ cat examples/bad.json | ./sd-proxy.py ./config-example.yaml -#### Qubes Integration +## Qubes Integration Until we determine how we wish to package and install this script, demonstrating the proxy in a Qubes environment is a somewhat manual diff --git a/proxy/build-requirements.txt b/proxy/build-requirements.txt deleted file mode 100644 index abbd5984e..000000000 --- a/proxy/build-requirements.txt +++ /dev/null @@ -1,6 +0,0 @@ -certifi==2023.7.22 --hash=sha256:920fc822272317b0d13e60eef0405ddd7f921e08dd21150a9eb613c863e31c2a -charset-normalizer==2.0.4 --hash=sha256:cd9a4492eef4e5276c07f9c0dc1338e7be3e95f2a536bf2c5b620b1f27d03d74 -idna==3.2 --hash=sha256:691d9fc304505c65ea9ceb8eb7385d63988e344c065cacbbd2156ff9bdfcf0c1 -pyyaml==5.4.1 --hash=sha256:9608c1b459ff310fe7fa78e8a9e12767a9a0ea9e3fa7cce116db58f95b61f56f --hash=sha256:f7190863a72d6eb89ed92e345e178a0803c439fd7126985b62c1c113cb01e534 -requests==2.31.0 --hash=sha256:9f7f0f507fe7a9e10ea51e666da60aafcfcda94c71f0cac477dbadd8d25de49f -urllib3==1.26.6 --hash=sha256:7a2814749409a681ab58babe6539b02a2f84f6649904211f90fb649811ae7b36 diff --git a/proxy/build.rs b/proxy/build.rs new file mode 100644 index 000000000..dac27c666 --- /dev/null +++ b/proxy/build.rs @@ -0,0 +1,36 @@ +use std::env; +use std::path::PathBuf; + +#[cfg(feature = "qubesdb")] +fn main() { + // Tell cargo to look for shared libraries in the specified directory + println!("cargo:rustc-link-search=/usr/lib"); + + // Tell cargo to tell rustc to link the system bzip2 + // shared library. + println!("cargo:rustc-link-lib=qubesdb"); + + // The bindgen::Builder is the main entry point + // to bindgen, and lets you build up options for + // the resulting bindings. + let bindings = bindgen::Builder::default() + // The input header we would like to generate + // bindings for. + .header("wrapper.h") + // Tell cargo to invalidate the built crate whenever any of the + // included header files changed. + .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) + // Finish the builder and generate the bindings. + .generate() + // Unwrap the Result and panic on failure. + .expect("Unable to generate bindings"); + + // Write the bindings to the $OUT_DIR/bindings.rs file. + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); +} + +#[cfg(not(feature = "qubesdb"))] +fn main() {} diff --git a/proxy/config-example.yaml b/proxy/config-example.yaml deleted file mode 100644 index 282052a86..000000000 --- a/proxy/config-example.yaml +++ /dev/null @@ -1,5 +0,0 @@ -host: jsonplaceholder.typicode.com -scheme: https -port: 443 -target_vm: compost -dev: False diff --git a/proxy/entrypoint.sh b/proxy/entrypoint.sh deleted file mode 100755 index 04b34fd33..000000000 --- a/proxy/entrypoint.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -cd /home/user/projects/securedrop-proxy -virtualenv .venv -source .venv/bin/activate -pip install --require-hashes -r requirements.txt -pip install --require-hashes -r dev-requirements.txt -./sd-proxy.py ./config.yaml diff --git a/proxy/examples/bad.json b/proxy/examples/bad.json deleted file mode 100644 index 141fce1e4..000000000 --- a/proxy/examples/bad.json +++ /dev/null @@ -1,2 +0,0 @@ -"foo": "bar", - "baz": "bliff" } diff --git a/proxy/examples/html.json b/proxy/examples/html.json deleted file mode 100644 index fa04743d3..000000000 --- a/proxy/examples/html.json +++ /dev/null @@ -1,2 +0,0 @@ -{ "method": "GET", - "path_query": "" } diff --git a/proxy/examples/posts.json b/proxy/examples/posts.json deleted file mode 100644 index 37c736c59..000000000 --- a/proxy/examples/posts.json +++ /dev/null @@ -1,2 +0,0 @@ -{ "method": "GET", - "path_query": "/posts?userId=1" } diff --git a/proxy/fixtures/basic_proxy_functionality.yaml b/proxy/fixtures/basic_proxy_functionality.yaml deleted file mode 100644 index 41b466bc9..000000000 --- a/proxy/fixtures/basic_proxy_functionality.yaml +++ /dev/null @@ -1,124 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: [application/json] - method: GET - uri: https://jsonplaceholder.typicode.com/ - response: - body: {string: "\n\n\n\n\n\n\n\n\nJSONPlaceholder - - Fake online REST API for developers\n\n\n\n\n
\n\n
\n

\n{\nJSON\n:\nPlaceholder\n}\n

\n

\nFake - Online REST API for Testing and Prototyping\n
Serving ~200 millions API - requests per month\n

\n

\nPowered by\nJSON - Server\nand\nLowDB\n

\n
\n\n
\n

Sponsors \U0001F64F

\n

\n\n\n\n

\n

\n[Become a sponsor]\n

\n
\n\n
\n
\n\n

Intro

\n

\nJSONPlaceholder is a - free online REST service that you can use whenever you need some fake data.\n
It's - great for tutorials, testing new libraries, sharing code examples, ...\n

\n\n

Example

\n

\nRun - this code in a console or from anywhere. Both\n

\n
fetch('https://jsonplaceholder.typicode.com/todos/1')\n
-        \ .then(response => response.json())\n  .then(json => console.log(json))\n
\n

\n\nAwesome - \U0001F942\n

\n
\n

\nTip - you can use\n\nhttp\n or\n\nhttps\n when making requests to - JSONPlaceholder.\n

\n\n

Resources

\n

\nJSONPlaceholder comes with - a set of common resources.\n

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n/posts\n100 posts
\n/comments\n500 comments
\n/albums\n100 albums
\n/photos\n5000 photos
\n/todos\n200 todos
\n/users\n10 users
\n

\nNote - resources have relations. For example:\nposts have many\ncomments,\nalbums - have many\nphotos, ...\n

\n\n

Routes

\n

\nAll HTTP methods - are supported.\n

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
GET\n/posts\n
GET\n/posts/1\n
GET\n/posts/1/comments\n
GET\n/comments?postId=1\n
GET\n/posts?userId=1\n
POST/posts
PUT/posts/1
PATCH/posts/1
DELETE/posts/1
\n

\nNote - you can view detailed examples\n\nhere\n\n

\n\n

Use - your own data

\n

\n\nJSON - Server\n powers this website. You can use it to create the same - fake API in less than\n30 seconds with your own data.\n

\n
npm install json-server
\n

You can also try\nMy JSON Server free service.

\n
\n
\n\n
\n

\nCoded - and built with \u2764\uFE0F by\ntypicode\n

\n

Source - code available on\nGitHub\n

\n

\n\n\n

\n
\n\n\n\n\n\n"} - headers: - Access-Control-Allow-Credentials: ['true'] - CF-Cache-Status: [HIT] - CF-RAY: [44b6eed6eeb06c7c-SJC] - Cache-Control: ['public, max-age=14400'] - Connection: [keep-alive] - Content-Type: [text/html; charset=UTF-8] - Date: ['Thu, 16 Aug 2018 21:18:21 GMT'] - Expect-CT: ['max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"'] - Expires: ['Fri, 17 Aug 2018 01:18:21 GMT'] - Last-Modified: ['Sun, 29 Jul 2018 21:56:24 GMT'] - Server: [cloudflare] - Set-Cookie: ['__cfduid=d2298f2ad2272eaf0907e88029489f22c1534454301; expires=Fri, - 16-Aug-19 21:18:21 GMT; path=/; domain=.typicode.com; HttpOnly'] - Vary: ['Origin, Accept-Encoding'] - Via: [1.1 vegur] - X-Powered-By: [Express] - status: {code: 200, message: OK} -version: 1 diff --git a/proxy/fixtures/main_error_response.yaml b/proxy/fixtures/main_error_response.yaml deleted file mode 100644 index 30d6fd734..000000000 --- a/proxy/fixtures/main_error_response.yaml +++ /dev/null @@ -1,30 +0,0 @@ -interactions: -- request: - body: null - headers: - Content-Length: - - '0' - method: '' - uri: https://jsonplaceholder.typicode.com/ - response: - body: - string: "\r\n400 Bad Request\r\n\r\n\ -

400 Bad Request

\r\n
cloudflare
\r\ - \n\r\n\r\n" - headers: - CF-RAY: - - '-' - Connection: - - close - Content-Length: - - '155' - Content-Type: - - text/html - Date: - - Mon, 16 Dec 2019 22:11:39 GMT - Server: - - cloudflare - status: - code: 400 - message: Bad Request -version: 1 diff --git a/proxy/fixtures/main_input_body.yaml b/proxy/fixtures/main_input_body.yaml deleted file mode 100644 index 0ea82b1a2..000000000 --- a/proxy/fixtures/main_input_body.yaml +++ /dev/null @@ -1,59 +0,0 @@ -interactions: -- request: - body: id=42&title=test - headers: - Content-Length: - - '16' - Content-Type: - - application/x-www-form-urlencoded - method: POST - uri: https://jsonplaceholder.typicode.com/posts - response: - body: - string: "{\n \"id\": 101,\n \"title\": \"test\"\n}" - headers: - Access-Control-Allow-Credentials: - - 'true' - Access-Control-Expose-Headers: - - Location - CF-Cache-Status: - - DYNAMIC - CF-RAY: - - 546ab6213f81f11a-IAD - Cache-Control: - - no-cache - Connection: - - keep-alive - Content-Length: - - '34' - Content-Type: - - application/json; charset=utf-8 - Date: - - Tue, 17 Dec 2019 17:45:33 GMT - Etag: - - W/"22-i04alCk7PdGrJ2UKCUwBOO0LB3w" - Expect-CT: - - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" - Expires: - - '-1' - Location: - - http://jsonplaceholder.typicode.com/posts/101 - Pragma: - - no-cache - Server: - - cloudflare - Set-Cookie: - - __cfduid=d1fa880178dc2db917f26b8ce4e0d56e41576604733; expires=Thu, 16-Jan-20 - 17:45:33 GMT; path=/; domain=.typicode.com; HttpOnly; SameSite=Lax - Vary: - - Origin, X-HTTP-Method-Override, Accept-Encoding - Via: - - 1.1 vegur - X-Content-Type-Options: - - nosniff - X-Powered-By: - - Express - status: - code: 201 - message: Created -version: 1 diff --git a/proxy/fixtures/main_input_headers.yaml b/proxy/fixtures/main_input_headers.yaml deleted file mode 100644 index 606bfa7ad..000000000 --- a/proxy/fixtures/main_input_headers.yaml +++ /dev/null @@ -1,94 +0,0 @@ -interactions: -- request: - body: null - headers: - X-Test-Header: - - th - method: GET - uri: https://jsonplaceholder.typicode.com/posts?userId=1 - response: - body: - string: "[\n {\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"sunt aut\ - \ facere repellat provident occaecati excepturi optio reprehenderit\",\n \ - \ \"body\": \"quia et suscipit\\nsuscipit recusandae consequuntur expedita\ - \ et cum\\nreprehenderit molestiae ut ut quas totam\\nnostrum rerum est autem\ - \ sunt rem eveniet architecto\"\n },\n {\n \"userId\": 1,\n \"id\"\ - : 2,\n \"title\": \"qui est esse\",\n \"body\": \"est rerum tempore\ - \ vitae\\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\\nfugiat\ - \ blanditiis voluptate porro vel nihil molestiae ut reiciendis\\nqui aperiam\ - \ non debitis possimus qui neque nisi nulla\"\n },\n {\n \"userId\":\ - \ 1,\n \"id\": 3,\n \"title\": \"ea molestias quasi exercitationem repellat\ - \ qui ipsa sit aut\",\n \"body\": \"et iusto sed quo iure\\nvoluptatem\ - \ occaecati omnis eligendi aut ad\\nvoluptatem doloribus vel accusantium quis\ - \ pariatur\\nmolestiae porro eius odio et labore et velit aut\"\n },\n {\n\ - \ \"userId\": 1,\n \"id\": 4,\n \"title\": \"eum et est occaecati\"\ - ,\n \"body\": \"ullam et saepe reiciendis voluptatem adipisci\\nsit amet\ - \ autem assumenda provident rerum culpa\\nquis hic commodi nesciunt rem tenetur\ - \ doloremque ipsam iure\\nquis sunt voluptatem rerum illo velit\"\n },\n\ - \ {\n \"userId\": 1,\n \"id\": 5,\n \"title\": \"nesciunt quas odio\"\ - ,\n \"body\": \"repudiandae veniam quaerat sunt sed\\nalias aut fugiat\ - \ sit autem sed est\\nvoluptatem omnis possimus esse voluptatibus quis\\nest\ - \ aut tenetur dolor neque\"\n },\n {\n \"userId\": 1,\n \"id\": 6,\n\ - \ \"title\": \"dolorem eum magni eos aperiam quia\",\n \"body\": \"\ - ut aspernatur corporis harum nihil quis provident sequi\\nmollitia nobis aliquid\ - \ molestiae\\nperspiciatis et ea nemo ab reprehenderit accusantium quas\\\ - nvoluptate dolores velit et doloremque molestiae\"\n },\n {\n \"userId\"\ - : 1,\n \"id\": 7,\n \"title\": \"magnam facilis autem\",\n \"body\"\ - : \"dolore placeat quibusdam ea quo vitae\\nmagni quis enim qui quis quo nemo\ - \ aut saepe\\nquidem repellat excepturi ut quia\\nsunt ut sequi eos ea sed\ - \ quas\"\n },\n {\n \"userId\": 1,\n \"id\": 8,\n \"title\": \"\ - dolorem dolore est ipsam\",\n \"body\": \"dignissimos aperiam dolorem qui\ - \ eum\\nfacilis quibusdam animi sint suscipit qui sint possimus cum\\nquaerat\ - \ magni maiores excepturi\\nipsam ut commodi dolor voluptatum modi aut vitae\"\ - \n },\n {\n \"userId\": 1,\n \"id\": 9,\n \"title\": \"nesciunt\ - \ iure omnis dolorem tempora et accusantium\",\n \"body\": \"consectetur\ - \ animi nesciunt iure dolore\\nenim quia ad\\nveniam autem ut quam aut nobis\\\ - net est aut quod aut provident voluptas autem voluptas\"\n },\n {\n \"\ - userId\": 1,\n \"id\": 10,\n \"title\": \"optio molestias id quia eum\"\ - ,\n \"body\": \"quo et expedita modi cum officia vel magni\\ndoloribus\ - \ qui repudiandae\\nvero nisi sit\\nquos veniam quod sed accusamus veritatis\ - \ error\"\n }\n]" - headers: - Access-Control-Allow-Credentials: - - 'true' - Age: - - '1789' - CF-Cache-Status: - - HIT - CF-RAY: - - 54722d954de5e0ea-IAD - Cache-Control: - - max-age=14400 - Connection: - - keep-alive - Content-Type: - - application/json; charset=utf-8 - Date: - - Wed, 18 Dec 2019 15:30:26 GMT - Etag: - - W/"aa6-j2NSH739l9uq40OywFMn7Y0C/iY" - Expect-CT: - - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" - Expires: - - '-1' - Pragma: - - no-cache - Server: - - cloudflare - Set-Cookie: - - __cfduid=d21e159ad4987bc5ba9d781aed2f9db5c1576683026; expires=Fri, 17-Jan-20 - 15:30:26 GMT; path=/; domain=.typicode.com; HttpOnly; SameSite=Lax - Transfer-Encoding: - - chunked - Vary: - - Origin, Accept-Encoding - Via: - - 1.1 vegur - X-Content-Type-Options: - - nosniff - X-Powered-By: - - Express - status: - code: 200 - message: OK -version: 1 diff --git a/proxy/fixtures/main_json_response.yaml b/proxy/fixtures/main_json_response.yaml deleted file mode 100644 index 782bee3e5..000000000 --- a/proxy/fixtures/main_json_response.yaml +++ /dev/null @@ -1,92 +0,0 @@ -interactions: -- request: - body: null - headers: {} - method: GET - uri: https://jsonplaceholder.typicode.com/posts?userId=1 - response: - body: - string: "[\n {\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"sunt aut\ - \ facere repellat provident occaecati excepturi optio reprehenderit\",\n \ - \ \"body\": \"quia et suscipit\\nsuscipit recusandae consequuntur expedita\ - \ et cum\\nreprehenderit molestiae ut ut quas totam\\nnostrum rerum est autem\ - \ sunt rem eveniet architecto\"\n },\n {\n \"userId\": 1,\n \"id\"\ - : 2,\n \"title\": \"qui est esse\",\n \"body\": \"est rerum tempore\ - \ vitae\\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\\nfugiat\ - \ blanditiis voluptate porro vel nihil molestiae ut reiciendis\\nqui aperiam\ - \ non debitis possimus qui neque nisi nulla\"\n },\n {\n \"userId\":\ - \ 1,\n \"id\": 3,\n \"title\": \"ea molestias quasi exercitationem repellat\ - \ qui ipsa sit aut\",\n \"body\": \"et iusto sed quo iure\\nvoluptatem\ - \ occaecati omnis eligendi aut ad\\nvoluptatem doloribus vel accusantium quis\ - \ pariatur\\nmolestiae porro eius odio et labore et velit aut\"\n },\n {\n\ - \ \"userId\": 1,\n \"id\": 4,\n \"title\": \"eum et est occaecati\"\ - ,\n \"body\": \"ullam et saepe reiciendis voluptatem adipisci\\nsit amet\ - \ autem assumenda provident rerum culpa\\nquis hic commodi nesciunt rem tenetur\ - \ doloremque ipsam iure\\nquis sunt voluptatem rerum illo velit\"\n },\n\ - \ {\n \"userId\": 1,\n \"id\": 5,\n \"title\": \"nesciunt quas odio\"\ - ,\n \"body\": \"repudiandae veniam quaerat sunt sed\\nalias aut fugiat\ - \ sit autem sed est\\nvoluptatem omnis possimus esse voluptatibus quis\\nest\ - \ aut tenetur dolor neque\"\n },\n {\n \"userId\": 1,\n \"id\": 6,\n\ - \ \"title\": \"dolorem eum magni eos aperiam quia\",\n \"body\": \"\ - ut aspernatur corporis harum nihil quis provident sequi\\nmollitia nobis aliquid\ - \ molestiae\\nperspiciatis et ea nemo ab reprehenderit accusantium quas\\\ - nvoluptate dolores velit et doloremque molestiae\"\n },\n {\n \"userId\"\ - : 1,\n \"id\": 7,\n \"title\": \"magnam facilis autem\",\n \"body\"\ - : \"dolore placeat quibusdam ea quo vitae\\nmagni quis enim qui quis quo nemo\ - \ aut saepe\\nquidem repellat excepturi ut quia\\nsunt ut sequi eos ea sed\ - \ quas\"\n },\n {\n \"userId\": 1,\n \"id\": 8,\n \"title\": \"\ - dolorem dolore est ipsam\",\n \"body\": \"dignissimos aperiam dolorem qui\ - \ eum\\nfacilis quibusdam animi sint suscipit qui sint possimus cum\\nquaerat\ - \ magni maiores excepturi\\nipsam ut commodi dolor voluptatum modi aut vitae\"\ - \n },\n {\n \"userId\": 1,\n \"id\": 9,\n \"title\": \"nesciunt\ - \ iure omnis dolorem tempora et accusantium\",\n \"body\": \"consectetur\ - \ animi nesciunt iure dolore\\nenim quia ad\\nveniam autem ut quam aut nobis\\\ - net est aut quod aut provident voluptas autem voluptas\"\n },\n {\n \"\ - userId\": 1,\n \"id\": 10,\n \"title\": \"optio molestias id quia eum\"\ - ,\n \"body\": \"quo et expedita modi cum officia vel magni\\ndoloribus\ - \ qui repudiandae\\nvero nisi sit\\nquos veniam quod sed accusamus veritatis\ - \ error\"\n }\n]" - headers: - Access-Control-Allow-Credentials: - - 'true' - Age: - - '4646' - CF-Cache-Status: - - HIT - CF-RAY: - - 54640259fa6fe0d2-IAD - Cache-Control: - - max-age=14400 - Connection: - - keep-alive - Content-Type: - - application/json; charset=utf-8 - Date: - - Mon, 16 Dec 2019 22:14:15 GMT - Etag: - - W/"aa6-j2NSH739l9uq40OywFMn7Y0C/iY" - Expect-CT: - - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" - Expires: - - '-1' - Pragma: - - no-cache - Server: - - cloudflare - Set-Cookie: - - __cfduid=d8ac1a396d31b9e9c1f816924e5bf186d1576534455; expires=Wed, 15-Jan-20 - 22:14:15 GMT; path=/; domain=.typicode.com; HttpOnly - Transfer-Encoding: - - chunked - Vary: - - Origin, Accept-Encoding - Via: - - 1.1 vegur - X-Content-Type-Options: - - nosniff - X-Powered-By: - - Express - status: - code: 200 - message: OK -version: 1 diff --git a/proxy/fixtures/main_json_response_with_timeout.yaml b/proxy/fixtures/main_json_response_with_timeout.yaml deleted file mode 100644 index f10ccee63..000000000 --- a/proxy/fixtures/main_json_response_with_timeout.yaml +++ /dev/null @@ -1,94 +0,0 @@ -interactions: -- request: - body: null - headers: {} - method: GET - uri: https://jsonplaceholder.typicode.com/posts?userId=1 - response: - body: - string: "[\n {\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"sunt aut\ - \ facere repellat provident occaecati excepturi optio reprehenderit\",\n \ - \ \"body\": \"quia et suscipit\\nsuscipit recusandae consequuntur expedita\ - \ et cum\\nreprehenderit molestiae ut ut quas totam\\nnostrum rerum est autem\ - \ sunt rem eveniet architecto\"\n },\n {\n \"userId\": 1,\n \"id\"\ - : 2,\n \"title\": \"qui est esse\",\n \"body\": \"est rerum tempore\ - \ vitae\\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\\nfugiat\ - \ blanditiis voluptate porro vel nihil molestiae ut reiciendis\\nqui aperiam\ - \ non debitis possimus qui neque nisi nulla\"\n },\n {\n \"userId\":\ - \ 1,\n \"id\": 3,\n \"title\": \"ea molestias quasi exercitationem repellat\ - \ qui ipsa sit aut\",\n \"body\": \"et iusto sed quo iure\\nvoluptatem\ - \ occaecati omnis eligendi aut ad\\nvoluptatem doloribus vel accusantium quis\ - \ pariatur\\nmolestiae porro eius odio et labore et velit aut\"\n },\n {\n\ - \ \"userId\": 1,\n \"id\": 4,\n \"title\": \"eum et est occaecati\"\ - ,\n \"body\": \"ullam et saepe reiciendis voluptatem adipisci\\nsit amet\ - \ autem assumenda provident rerum culpa\\nquis hic commodi nesciunt rem tenetur\ - \ doloremque ipsam iure\\nquis sunt voluptatem rerum illo velit\"\n },\n\ - \ {\n \"userId\": 1,\n \"id\": 5,\n \"title\": \"nesciunt quas odio\"\ - ,\n \"body\": \"repudiandae veniam quaerat sunt sed\\nalias aut fugiat\ - \ sit autem sed est\\nvoluptatem omnis possimus esse voluptatibus quis\\nest\ - \ aut tenetur dolor neque\"\n },\n {\n \"userId\": 1,\n \"id\": 6,\n\ - \ \"title\": \"dolorem eum magni eos aperiam quia\",\n \"body\": \"\ - ut aspernatur corporis harum nihil quis provident sequi\\nmollitia nobis aliquid\ - \ molestiae\\nperspiciatis et ea nemo ab reprehenderit accusantium quas\\\ - nvoluptate dolores velit et doloremque molestiae\"\n },\n {\n \"userId\"\ - : 1,\n \"id\": 7,\n \"title\": \"magnam facilis autem\",\n \"body\"\ - : \"dolore placeat quibusdam ea quo vitae\\nmagni quis enim qui quis quo nemo\ - \ aut saepe\\nquidem repellat excepturi ut quia\\nsunt ut sequi eos ea sed\ - \ quas\"\n },\n {\n \"userId\": 1,\n \"id\": 8,\n \"title\": \"\ - dolorem dolore est ipsam\",\n \"body\": \"dignissimos aperiam dolorem qui\ - \ eum\\nfacilis quibusdam animi sint suscipit qui sint possimus cum\\nquaerat\ - \ magni maiores excepturi\\nipsam ut commodi dolor voluptatum modi aut vitae\"\ - \n },\n {\n \"userId\": 1,\n \"id\": 9,\n \"title\": \"nesciunt\ - \ iure omnis dolorem tempora et accusantium\",\n \"body\": \"consectetur\ - \ animi nesciunt iure dolore\\nenim quia ad\\nveniam autem ut quam aut nobis\\\ - net est aut quod aut provident voluptas autem voluptas\"\n },\n {\n \"\ - userId\": 1,\n \"id\": 10,\n \"title\": \"optio molestias id quia eum\"\ - ,\n \"body\": \"quo et expedita modi cum officia vel magni\\ndoloribus\ - \ qui repudiandae\\nvero nisi sit\\nquos veniam quod sed accusamus veritatis\ - \ error\"\n }\n]" - headers: - Access-Control-Allow-Credentials: - - 'true' - Age: - - '53198' - CF-Cache-Status: - - STALE - CF-RAY: - - 59b0b761ace6fe12-DTW - Cache-Control: - - max-age=14400 - Connection: - - keep-alive - Content-Type: - - application/json; charset=utf-8 - Date: - - Fri, 29 May 2020 13:56:31 GMT - Etag: - - W/"aa6-j2NSH739l9uq40OywFMn7Y0C/iY" - Expect-CT: - - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" - Expires: - - '-1' - Pragma: - - no-cache - Server: - - cloudflare - Set-Cookie: - - __cfduid=d259d305f25abe26719e6850ce4b06cae1590760560; expires=Sun, 28-Jun-20 - 13:56:00 GMT; path=/; domain=.typicode.com; HttpOnly; SameSite=Lax - Transfer-Encoding: - - chunked - Vary: - - Origin, Accept-Encoding - Via: - - 1.1 vegur - X-Content-Type-Options: - - nosniff - X-Powered-By: - - Express - cf-request-id: - - 030250f1080000fe12a1a71200000001 - status: - code: 200 - message: OK -version: 1 diff --git a/proxy/fixtures/main_non_json_response.yaml b/proxy/fixtures/main_non_json_response.yaml deleted file mode 100644 index e5e02a920..000000000 --- a/proxy/fixtures/main_non_json_response.yaml +++ /dev/null @@ -1,145 +0,0 @@ -interactions: -- request: - body: null - headers: {} - method: GET - uri: https://jsonplaceholder.typicode.com/ - response: - body: - string: "\n\n\n\n\n\n\n\n\n\n\nJSONPlaceholder - Fake online REST API for developers\n\ - \n\n
\n\n\ - \n Announcement: You can now support\n\ - JSONPlaceholder on GitHub Sponsors!\n\n
\n
\n\n
\n
\n

\nJSONPlaceholder\n\ -

\n

\nFake Online REST API for Testing and Prototyping\n\ -
Serving ~350M requests per month\n
Powered by\nJSON Server\n+\nLowDB\n

\n\n\n\n\n\n
\n
\n\n
\n

Gold\ - \ Sponsors

\n

\n\n\n\n

\n

\nYour Company Logo Here\n

\n
\n\n
\n
\n\ - \n

Intro

\n

\nJSONPlaceholder is a free online REST API that you\ - \ can use whenever you need some fake data.\n
It's great for tutorials,\ - \ testing new libraries, sharing code examples, ...\n

\n\n

Example

\n\ -

\nRun this code in a console or from any site:\n

\n
fetch('https://jsonplaceholder.typicode.com/todos/1')\n\
-        \  .then(response => response.json())\n  .then(json => console.log(json))\n\
-        
\n

\n\n

\n
\nCongrats\ - \ you've made your first call to JSONPlaceholder! \U0001F603 \U0001F389\n\ -

\nTip: you can use\n\nhttp://\n or\n\nhttps://\n\ - when making requests to JSONPlaceholder.\n

\n
\n\n\n

Resources

\n

\nJSONPlaceholder comes with a\ - \ set of 6 common resources:\n

\n\n\n\n\n\n\n\ - \n\n\ - \n\n\n\n\ - \n\n\n\n\ - \n\n\n\n\ - \n\n\n\n\ - \n
\n\ - \ /posts\n100 posts
\n/comments\n500 comments
\n/albums\n100 albums
\n/photos\n5000 photos
\n/todos\n200 todos
\n/users\n10 users
\n

\nNote: resources have relations. For\ - \ example:\nposts have many\ncomments,\nalbums have many\n\ - photos, ... see below for routes examples.\n

\n\n

Routes

\n\ -

\nAll HTTP methods are supported.\n

\n\n\n\n\ - \n\n\n\n\n\n\n\n\n\n\n\ - \n\n\n\n\n\n\n\n\n\n\n\n\n\ - \n\n\n\n\n\n\ - \n\n\n\n\n
GET\n/posts\n
GET\n\ - /posts/1\n
GET\n\ - /posts/1/comments\n
GET\n/comments?postId=1\n\ -
GET\n/posts?userId=1\n\ -
POST/posts
PUT/posts/1
PATCH/posts/1
DELETE/posts/1
\n

\nNote:\ - \ you can view detailed examples\nhere.\n

\n\ - \n

Use your own data

\n\n

\nWith My JSON Server online service and a simple GitHub repo, you can have\ - \ your own online fake REST server in seconds.\n

\n
\n
\n
\n\ - \n\n\n\n\n\ - \n\n\n" - headers: - Access-Control-Allow-Credentials: - - 'true' - Age: - - '5668' - CF-Cache-Status: - - HIT - CF-RAY: - - 5463fe6ccb0ecf04-IAD - Cache-Control: - - public, max-age=14400 - Connection: - - keep-alive - Content-Type: - - text/html; charset=UTF-8 - Date: - - Mon, 16 Dec 2019 22:11:34 GMT - Expect-CT: - - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" - Last-Modified: - - Mon, 05 Aug 2019 03:07:14 GMT - Server: - - cloudflare - Set-Cookie: - - __cfduid=d13b55a7f6e786f74d5f9f1f084a183a31576534294; expires=Wed, 15-Jan-20 - 22:11:34 GMT; path=/; domain=.typicode.com; HttpOnly - Transfer-Encoding: - - chunked - Vary: - - Origin, Accept-Encoding - Via: - - 1.1 vegur - X-Powered-By: - - Express - status: - code: 200 - message: OK -version: 1 diff --git a/proxy/fixtures/proxy_200_valid_path.yaml b/proxy/fixtures/proxy_200_valid_path.yaml deleted file mode 100644 index ef116fd88..000000000 --- a/proxy/fixtures/proxy_200_valid_path.yaml +++ /dev/null @@ -1,34 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: [application/json] - method: GET - uri: https://jsonplaceholder.typicode.com/posts/1 - response: - body: {string: "{\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"sunt aut facere - repellat provident occaecati excepturi optio reprehenderit\",\n \"body\": - \"quia et suscipit\\nsuscipit recusandae consequuntur expedita et cum\\nreprehenderit - molestiae ut ut quas totam\\nnostrum rerum est autem sunt rem eveniet architecto\"\n}"} - headers: - Access-Control-Allow-Credentials: ['true'] - CF-Cache-Status: [HIT] - CF-RAY: [44b7cfc9cd806c58-SJC] - Cache-Control: ['public, max-age=14400'] - Connection: [keep-alive] - Content-Length: ['292'] - Content-Type: [application/json; charset=utf-8] - Date: ['Thu, 16 Aug 2018 23:51:55 GMT'] - Etag: [W/"124-yiKdLzqO5gfBrJFrcdJ8Yq0LGnU"] - Expect-CT: ['max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"'] - Expires: ['Fri, 17 Aug 2018 03:51:55 GMT'] - Pragma: [no-cache] - Server: [cloudflare] - Set-Cookie: ['__cfduid=d5d93decbd21c24b97c90d1f49461fd8d1534463515; expires=Fri, - 16-Aug-19 23:51:55 GMT; path=/; domain=.typicode.com; HttpOnly'] - Vary: ['Origin, Accept-Encoding'] - Via: [1.1 vegur] - X-Content-Type-Options: [nosniff] - X-Powered-By: [Express] - status: {code: 200, message: OK} -version: 1 diff --git a/proxy/fixtures/proxy_404.yaml b/proxy/fixtures/proxy_404.yaml deleted file mode 100644 index 491699a10..000000000 --- a/proxy/fixtures/proxy_404.yaml +++ /dev/null @@ -1,31 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: [application/json] - method: GET - uri: https://jsonplaceholder.typicode.com/notfound - response: - body: {string: '{}'} - headers: - Access-Control-Allow-Credentials: ['true'] - CF-Cache-Status: [HIT] - CF-RAY: [44b75f42af366c82-SJC] - Cache-Control: ['public, max-age=14400'] - Connection: [keep-alive] - Content-Length: ['2'] - Content-Type: [application/json; charset=utf-8] - Date: ['Thu, 16 Aug 2018 22:35:06 GMT'] - Etag: [W/"2-vyGp6PvFo4RvsFtPoIWeCReyIC8"] - Expect-CT: ['max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"'] - Expires: ['Fri, 17 Aug 2018 02:35:06 GMT'] - Pragma: [no-cache] - Server: [cloudflare] - Set-Cookie: ['__cfduid=d1ba26b900bf8e93056964a66047938871534458906; expires=Fri, - 16-Aug-19 22:35:06 GMT; path=/; domain=.typicode.com; HttpOnly'] - Vary: ['Origin, Accept-Encoding'] - Via: [1.1 vegur] - X-Content-Type-Options: [nosniff] - X-Powered-By: [Express] - status: {code: 404, message: Not Found} -version: 1 diff --git a/proxy/fixtures/proxy_bad_request.yaml b/proxy/fixtures/proxy_bad_request.yaml deleted file mode 100644 index 9d71f3dae..000000000 --- a/proxy/fixtures/proxy_bad_request.yaml +++ /dev/null @@ -1,20 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - method: GET - uri: http://localhost:8000/bad - response: - body: - string: '' - headers: - Date: - - Mon, 16 Dec 2019 23:44:53 GMT - Server: - - BaseHTTP/0.6 Python/3.7.3 - status: - code: 400 - message: Bad Request -version: 1 diff --git a/proxy/fixtures/proxy_callbacks.yaml b/proxy/fixtures/proxy_callbacks.yaml deleted file mode 100644 index 7224c8cfd..000000000 --- a/proxy/fixtures/proxy_callbacks.yaml +++ /dev/null @@ -1,145 +0,0 @@ -interactions: -- request: - body: null - headers: {} - method: GET - uri: https://jsonplaceholder.typicode.com/ - response: - body: - string: "\n\n\n\n\n\n\n\n\n\n\nJSONPlaceholder - Fake online REST API for developers\n\ - \n\n
\n\n\ - \n Announcement: You can now support\n\ - JSONPlaceholder on GitHub Sponsors!\n\n
\n
\n\n
\n
\n

\nJSONPlaceholder\n\ -

\n

\nFake Online REST API for Testing and Prototyping\n\ -
Serving ~350M requests per month\n
Powered by\nJSON Server\n+\nLowDB\n

\n\n\n\n\n\n
\n
\n\n
\n

Gold\ - \ Sponsors

\n

\n\n\n\n

\n

\nYour Company Logo Here\n

\n
\n\n
\n
\n\ - \n

Intro

\n

\nJSONPlaceholder is a free online REST API that you\ - \ can use whenever you need some fake data.\n
It's great for tutorials,\ - \ testing new libraries, sharing code examples, ...\n

\n\n

Example

\n\ -

\nRun this code in a console or from any site:\n

\n
fetch('https://jsonplaceholder.typicode.com/todos/1')\n\
-        \  .then(response => response.json())\n  .then(json => console.log(json))\n\
-        
\n

\n\n

\n
\nCongrats\ - \ you've made your first call to JSONPlaceholder! \U0001F603 \U0001F389\n\ -

\nTip: you can use\n\nhttp://\n or\n\nhttps://\n\ - when making requests to JSONPlaceholder.\n

\n
\n\n\n

Resources

\n

\nJSONPlaceholder comes with a\ - \ set of 6 common resources:\n

\n\n\n\n\n\n\n\ - \n\n\ - \n\n\n\n\ - \n\n\n\n\ - \n\n\n\n\ - \n\n\n\n\ - \n
\n\ - \ /posts\n100 posts
\n/comments\n500 comments
\n/albums\n100 albums
\n/photos\n5000 photos
\n/todos\n200 todos
\n/users\n10 users
\n

\nNote: resources have relations. For\ - \ example:\nposts have many\ncomments,\nalbums have many\n\ - photos, ... see below for routes examples.\n

\n\n

Routes

\n\ -

\nAll HTTP methods are supported.\n

\n\n\n\n\ - \n\n\n\n\n\n\n\n\n\n\n\ - \n\n\n\n\n\n\n\n\n\n\n\n\n\ - \n\n\n\n\n\n\ - \n\n\n\n\n
GET\n/posts\n
GET\n\ - /posts/1\n
GET\n\ - /posts/1/comments\n
GET\n/comments?postId=1\n\ -
GET\n/posts?userId=1\n\ -
POST/posts
PUT/posts/1
PATCH/posts/1
DELETE/posts/1
\n

\nNote:\ - \ you can view detailed examples\nhere.\n

\n\ - \n

Use your own data

\n\n

\nWith My JSON Server online service and a simple GitHub repo, you can have\ - \ your own online fake REST server in seconds.\n

\n
\n
\n
\n\ - \n\n\n\n\n\ - \n\n\n" - headers: - Access-Control-Allow-Credentials: - - 'true' - Age: - - '4432' - CF-Cache-Status: - - HIT - CF-RAY: - - 5469de47682ecf00-IAD - Cache-Control: - - public, max-age=14400 - Connection: - - keep-alive - Content-Type: - - text/html; charset=UTF-8 - Date: - - Tue, 17 Dec 2019 15:18:12 GMT - Expect-CT: - - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" - Last-Modified: - - Mon, 05 Aug 2019 03:07:14 GMT - Server: - - cloudflare - Set-Cookie: - - __cfduid=dc33ebab29f22c648b958d03fed5596b51576595892; expires=Thu, 16-Jan-20 - 15:18:12 GMT; path=/; domain=.typicode.com; HttpOnly; SameSite=Lax - Transfer-Encoding: - - chunked - Vary: - - Origin, Accept-Encoding - Via: - - 1.1 vegur - X-Powered-By: - - Express - status: - code: 200 - message: OK -version: 1 diff --git a/proxy/fixtures/proxy_cannot_connect.yaml b/proxy/fixtures/proxy_cannot_connect.yaml deleted file mode 100644 index 9788ab4e4..000000000 --- a/proxy/fixtures/proxy_cannot_connect.yaml +++ /dev/null @@ -1,22 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - method: GET - uri: http://localhost:8000/ - response: - body: - string: 'hello - - ' - headers: - Date: - - Tue, 17 Dec 2019 00:06:22 GMT - Server: - - BaseHTTP/0.6 Python/3.7.3 - status: - code: 200 - message: OK -version: 1 diff --git a/proxy/fixtures/proxy_internal_error.yaml b/proxy/fixtures/proxy_internal_error.yaml deleted file mode 100644 index 7295de697..000000000 --- a/proxy/fixtures/proxy_internal_error.yaml +++ /dev/null @@ -1,22 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - method: GET - uri: http://localhost:8000/ - response: - body: - string: 'hello - - ' - headers: - Date: - - Tue, 17 Dec 2019 00:00:13 GMT - Server: - - BaseHTTP/0.6 Python/3.7.3 - status: - code: 200 - message: OK -version: 1 diff --git a/proxy/fixtures/proxy_internal_server_error.yaml b/proxy/fixtures/proxy_internal_server_error.yaml deleted file mode 100644 index 603e62467..000000000 --- a/proxy/fixtures/proxy_internal_server_error.yaml +++ /dev/null @@ -1,20 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - method: GET - uri: http://localhost:8000/crash - response: - body: - string: '' - headers: - Date: - - Mon, 16 Dec 2019 23:58:10 GMT - Server: - - BaseHTTP/0.6 Python/3.7.3 - status: - code: 500 - message: Internal Server Error -version: 1 diff --git a/proxy/fixtures/proxy_parameters.yaml b/proxy/fixtures/proxy_parameters.yaml deleted file mode 100644 index af1b06ffe..000000000 --- a/proxy/fixtures/proxy_parameters.yaml +++ /dev/null @@ -1,67 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: [application/json] - method: GET - uri: https://jsonplaceholder.typicode.com/posts?userId=1 - response: - body: {string: "[\n {\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"sunt - aut facere repellat provident occaecati excepturi optio reprehenderit\",\n - \ \"body\": \"quia et suscipit\\nsuscipit recusandae consequuntur expedita - et cum\\nreprehenderit molestiae ut ut quas totam\\nnostrum rerum est autem - sunt rem eveniet architecto\"\n },\n {\n \"userId\": 1,\n \"id\": - 2,\n \"title\": \"qui est esse\",\n \"body\": \"est rerum tempore vitae\\nsequi - sint nihil reprehenderit dolor beatae ea dolores neque\\nfugiat blanditiis - voluptate porro vel nihil molestiae ut reiciendis\\nqui aperiam non debitis - possimus qui neque nisi nulla\"\n },\n {\n \"userId\": 1,\n \"id\": - 3,\n \"title\": \"ea molestias quasi exercitationem repellat qui ipsa sit - aut\",\n \"body\": \"et iusto sed quo iure\\nvoluptatem occaecati omnis - eligendi aut ad\\nvoluptatem doloribus vel accusantium quis pariatur\\nmolestiae - porro eius odio et labore et velit aut\"\n },\n {\n \"userId\": 1,\n - \ \"id\": 4,\n \"title\": \"eum et est occaecati\",\n \"body\": \"ullam - et saepe reiciendis voluptatem adipisci\\nsit amet autem assumenda provident - rerum culpa\\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\\nquis - sunt voluptatem rerum illo velit\"\n },\n {\n \"userId\": 1,\n \"id\": - 5,\n \"title\": \"nesciunt quas odio\",\n \"body\": \"repudiandae veniam - quaerat sunt sed\\nalias aut fugiat sit autem sed est\\nvoluptatem omnis possimus - esse voluptatibus quis\\nest aut tenetur dolor neque\"\n },\n {\n \"userId\": - 1,\n \"id\": 6,\n \"title\": \"dolorem eum magni eos aperiam quia\",\n - \ \"body\": \"ut aspernatur corporis harum nihil quis provident sequi\\nmollitia - nobis aliquid molestiae\\nperspiciatis et ea nemo ab reprehenderit accusantium - quas\\nvoluptate dolores velit et doloremque molestiae\"\n },\n {\n \"userId\": - 1,\n \"id\": 7,\n \"title\": \"magnam facilis autem\",\n \"body\": - \"dolore placeat quibusdam ea quo vitae\\nmagni quis enim qui quis quo nemo - aut saepe\\nquidem repellat excepturi ut quia\\nsunt ut sequi eos ea sed quas\"\n - \ },\n {\n \"userId\": 1,\n \"id\": 8,\n \"title\": \"dolorem dolore - est ipsam\",\n \"body\": \"dignissimos aperiam dolorem qui eum\\nfacilis - quibusdam animi sint suscipit qui sint possimus cum\\nquaerat magni maiores - excepturi\\nipsam ut commodi dolor voluptatum modi aut vitae\"\n },\n {\n - \ \"userId\": 1,\n \"id\": 9,\n \"title\": \"nesciunt iure omnis dolorem - tempora et accusantium\",\n \"body\": \"consectetur animi nesciunt iure - dolore\\nenim quia ad\\nveniam autem ut quam aut nobis\\net est aut quod aut - provident voluptas autem voluptas\"\n },\n {\n \"userId\": 1,\n \"id\": - 10,\n \"title\": \"optio molestias id quia eum\",\n \"body\": \"quo - et expedita modi cum officia vel magni\\ndoloribus qui repudiandae\\nvero - nisi sit\\nquos veniam quod sed accusamus veritatis error\"\n }\n]"} - headers: - Access-Control-Allow-Credentials: ['true'] - CF-Cache-Status: [HIT] - CF-RAY: [44b7bdac4e0a6bf8-SJC] - Cache-Control: ['public, max-age=14400'] - Connection: [keep-alive] - Content-Type: [application/json; charset=utf-8] - Date: ['Thu, 16 Aug 2018 23:39:33 GMT'] - Etag: [W/"aa6-j2NSH739l9uq40OywFMn7Y0C/iY"] - Expect-CT: ['max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"'] - Expires: ['Fri, 17 Aug 2018 03:39:33 GMT'] - Pragma: [no-cache] - Server: [cloudflare] - Set-Cookie: ['__cfduid=dca3d39adfb7f9a82e73277f19cf335921534462773; expires=Fri, - 16-Aug-19 23:39:33 GMT; path=/; domain=.typicode.com; HttpOnly'] - Vary: ['Origin, Accept-Encoding'] - Via: [1.1 vegur] - X-Content-Type-Options: [nosniff] - X-Powered-By: [Express] - status: {code: 200, message: OK} -version: 1 diff --git a/proxy/fixtures/proxy_unofficial_status.yaml b/proxy/fixtures/proxy_unofficial_status.yaml deleted file mode 100644 index e0b7a193d..000000000 --- a/proxy/fixtures/proxy_unofficial_status.yaml +++ /dev/null @@ -1,20 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - method: GET - uri: http://localhost:8000/teapot - response: - body: - string: '' - headers: - Date: - - Mon, 16 Dec 2019 23:59:52 GMT - Server: - - BaseHTTP/0.6 Python/3.7.3 - status: - code: 499 - message: '' -version: 1 diff --git a/proxy/poetry.lock b/proxy/poetry.lock index 46e4e4d49..cb92f2549 100644 --- a/proxy/poetry.lock +++ b/proxy/poetry.lock @@ -1,616 +1,875 @@ # This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. [[package]] -name = "certifi" -version = "2023.7.22" -description = "Python package for providing Mozilla's CA Bundle." +name = "attrs" +version = "23.2.0" +description = "Classes Without Boilerplate" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, - {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, ] +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] + [[package]] -name = "charset-normalizer" -version = "2.0.4" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +name = "brotlicffi" +version = "1.1.0.0" +description = "Python CFFI bindings to the Brotli library" optional = false -python-versions = ">=3.5.0" +python-versions = ">=3.7" files = [ - {file = "charset-normalizer-2.0.4.tar.gz", hash = "sha256:f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3"}, - {file = "charset_normalizer-2.0.4-py3-none-any.whl", hash = "sha256:0c8911edd15d19223366a194a513099a302055a962bca2cec0f54b8b63175d8b"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9b7ae6bd1a3f0df532b6d67ff674099a96d22bc0948955cb338488c31bfb8851"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19ffc919fa4fc6ace69286e0a23b3789b4219058313cf9b45625016bf7ff996b"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9feb210d932ffe7798ee62e6145d3a757eb6233aa9a4e7db78dd3690d7755814"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84763dbdef5dd5c24b75597a77e1b30c66604725707565188ba54bab4f114820"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-win32.whl", hash = "sha256:1b12b50e07c3911e1efa3a8971543e7648100713d4e0971b13631cce22c587eb"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:994a4f0681bb6c6c3b0925530a1926b7a189d878e6e5e38fae8efa47c5d9c613"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2e4aeb0bd2540cb91b069dbdd54d458da8c4334ceaf2d25df2f4af576d6766ca"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b7b0033b0d37bb33009fb2fef73310e432e76f688af76c156b3594389d81391"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54a07bb2374a1eba8ebb52b6fafffa2afd3c4df85ddd38fcc0511f2bb387c2a8"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7901a7dc4b88f1c1475de59ae9be59799db1007b7d059817948d8e4f12e24e35"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ce01c7316aebc7fce59da734286148b1d1b9455f89cf2c8a4dfce7d41db55c2d"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:246f1d1a90279bb6069de3de8d75a8856e073b8ff0b09dcca18ccc14cec85979"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc4bc5d82bc56ebd8b514fb8350cfac4627d6b0743382e46d033976a5f80fab6"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37c26ecb14386a44b118ce36e546ce307f4810bc9598a6e6cb4f7fca725ae7e6"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca72968ae4eaf6470498d5c2887073f7efe3b1e7d7ec8be11a06a79cc810e990"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:add0de5b9ad9e9aa293c3aa4e9deb2b61e99ad6c1634e01d01d98c03e6a354cc"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9b6068e0f3769992d6b622a1cd2e7835eae3cf8d9da123d7f51ca9c1e9c333e5"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8557a8559509b61e65083f8782329188a250102372576093c88930c875a69838"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a7ae37e5d79c5bdfb5b4b99f2715a6035e6c5bf538c3746abc8e26694f92f33"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391151ec86bb1c683835980f4816272a87eaddc46bb91cbf44f62228b84d8cca"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2f3711be9290f0453de8eed5275d93d286abe26b08ab4a35d7452caa1fef532f"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1a807d760763e398bbf2c6394ae9da5815901aa93ee0a37bca5efe78d4ee3171"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa8ca0623b26c94fccc3a1fdd895be1743b838f3917300506d04aa3346fd2a14"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3de0cf28a53a3238b252aca9fed1593e9d36c1d116748013339f0949bfc84112"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6be5ec0e88a4925c91f3dea2bb0013b3a2accda6f77238f76a34a1ea532a1cb0"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d9eb71bb1085d996244439154387266fd23d6ad37161f6f52f1cd41dd95a3808"}, + {file = "brotlicffi-1.1.0.0.tar.gz", hash = "sha256:b77827a689905143f87915310b93b273ab17888fd43ef350d4832c4a71083c13"}, ] -[package.extras] -unicode-backport = ["unicodedata2"] +[package.dependencies] +cffi = ">=1.0.0" [[package]] -name = "coverage" -version = "7.3.0" -description = "Code coverage measurement for Python" +name = "cffi" +version = "1.16.0" +description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db76a1bcb51f02b2007adacbed4c88b6dee75342c37b05d1822815eed19edee5"}, - {file = "coverage-7.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c02cfa6c36144ab334d556989406837336c1d05215a9bdf44c0bc1d1ac1cb637"}, - {file = "coverage-7.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:477c9430ad5d1b80b07f3c12f7120eef40bfbf849e9e7859e53b9c93b922d2af"}, - {file = "coverage-7.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce2ee86ca75f9f96072295c5ebb4ef2a43cecf2870b0ca5e7a1cbdd929cf67e1"}, - {file = "coverage-7.3.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68d8a0426b49c053013e631c0cdc09b952d857efa8f68121746b339912d27a12"}, - {file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b3eb0c93e2ea6445b2173da48cb548364f8f65bf68f3d090404080d338e3a689"}, - {file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:90b6e2f0f66750c5a1178ffa9370dec6c508a8ca5265c42fbad3ccac210a7977"}, - {file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:96d7d761aea65b291a98c84e1250cd57b5b51726821a6f2f8df65db89363be51"}, - {file = "coverage-7.3.0-cp310-cp310-win32.whl", hash = "sha256:63c5b8ecbc3b3d5eb3a9d873dec60afc0cd5ff9d9f1c75981d8c31cfe4df8527"}, - {file = "coverage-7.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:97c44f4ee13bce914272589b6b41165bbb650e48fdb7bd5493a38bde8de730a1"}, - {file = "coverage-7.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:74c160285f2dfe0acf0f72d425f3e970b21b6de04157fc65adc9fd07ee44177f"}, - {file = "coverage-7.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b543302a3707245d454fc49b8ecd2c2d5982b50eb63f3535244fd79a4be0c99d"}, - {file = "coverage-7.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad0f87826c4ebd3ef484502e79b39614e9c03a5d1510cfb623f4a4a051edc6fd"}, - {file = "coverage-7.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:13c6cbbd5f31211d8fdb477f0f7b03438591bdd077054076eec362cf2207b4a7"}, - {file = "coverage-7.3.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fac440c43e9b479d1241fe9d768645e7ccec3fb65dc3a5f6e90675e75c3f3e3a"}, - {file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3c9834d5e3df9d2aba0275c9f67989c590e05732439b3318fa37a725dff51e74"}, - {file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4c8e31cf29b60859876474034a83f59a14381af50cbe8a9dbaadbf70adc4b214"}, - {file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7a9baf8e230f9621f8e1d00c580394a0aa328fdac0df2b3f8384387c44083c0f"}, - {file = "coverage-7.3.0-cp311-cp311-win32.whl", hash = "sha256:ccc51713b5581e12f93ccb9c5e39e8b5d4b16776d584c0f5e9e4e63381356482"}, - {file = "coverage-7.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:887665f00ea4e488501ba755a0e3c2cfd6278e846ada3185f42d391ef95e7e70"}, - {file = "coverage-7.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d000a739f9feed900381605a12a61f7aaced6beae832719ae0d15058a1e81c1b"}, - {file = "coverage-7.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:59777652e245bb1e300e620ce2bef0d341945842e4eb888c23a7f1d9e143c446"}, - {file = "coverage-7.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9737bc49a9255d78da085fa04f628a310c2332b187cd49b958b0e494c125071"}, - {file = "coverage-7.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5247bab12f84a1d608213b96b8af0cbb30d090d705b6663ad794c2f2a5e5b9fe"}, - {file = "coverage-7.3.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2ac9a1de294773b9fa77447ab7e529cf4fe3910f6a0832816e5f3d538cfea9a"}, - {file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:85b7335c22455ec12444cec0d600533a238d6439d8d709d545158c1208483873"}, - {file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:36ce5d43a072a036f287029a55b5c6a0e9bd73db58961a273b6dc11a2c6eb9c2"}, - {file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:211a4576e984f96d9fce61766ffaed0115d5dab1419e4f63d6992b480c2bd60b"}, - {file = "coverage-7.3.0-cp312-cp312-win32.whl", hash = "sha256:56afbf41fa4a7b27f6635bc4289050ac3ab7951b8a821bca46f5b024500e6321"}, - {file = "coverage-7.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f297e0c1ae55300ff688568b04ff26b01c13dfbf4c9d2b7d0cb688ac60df479"}, - {file = "coverage-7.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac0dec90e7de0087d3d95fa0533e1d2d722dcc008bc7b60e1143402a04c117c1"}, - {file = "coverage-7.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:438856d3f8f1e27f8e79b5410ae56650732a0dcfa94e756df88c7e2d24851fcd"}, - {file = "coverage-7.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1084393c6bda8875c05e04fce5cfe1301a425f758eb012f010eab586f1f3905e"}, - {file = "coverage-7.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49ab200acf891e3dde19e5aa4b0f35d12d8b4bd805dc0be8792270c71bd56c54"}, - {file = "coverage-7.3.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a67e6bbe756ed458646e1ef2b0778591ed4d1fcd4b146fc3ba2feb1a7afd4254"}, - {file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8f39c49faf5344af36042b293ce05c0d9004270d811c7080610b3e713251c9b0"}, - {file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7df91fb24c2edaabec4e0eee512ff3bc6ec20eb8dccac2e77001c1fe516c0c84"}, - {file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:34f9f0763d5fa3035a315b69b428fe9c34d4fc2f615262d6be3d3bf3882fb985"}, - {file = "coverage-7.3.0-cp38-cp38-win32.whl", hash = "sha256:bac329371d4c0d456e8d5f38a9b0816b446581b5f278474e416ea0c68c47dcd9"}, - {file = "coverage-7.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:b859128a093f135b556b4765658d5d2e758e1fae3e7cc2f8c10f26fe7005e543"}, - {file = "coverage-7.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fc0ed8d310afe013db1eedd37176d0839dc66c96bcfcce8f6607a73ffea2d6ba"}, - {file = "coverage-7.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61260ec93f99f2c2d93d264b564ba912bec502f679793c56f678ba5251f0393"}, - {file = "coverage-7.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97af9554a799bd7c58c0179cc8dbf14aa7ab50e1fd5fa73f90b9b7215874ba28"}, - {file = "coverage-7.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3558e5b574d62f9c46b76120a5c7c16c4612dc2644c3d48a9f4064a705eaee95"}, - {file = "coverage-7.3.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37d5576d35fcb765fca05654f66aa71e2808d4237d026e64ac8b397ffa66a56a"}, - {file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:07ea61bcb179f8f05ffd804d2732b09d23a1238642bf7e51dad62082b5019b34"}, - {file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:80501d1b2270d7e8daf1b64b895745c3e234289e00d5f0e30923e706f110334e"}, - {file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4eddd3153d02204f22aef0825409091a91bf2a20bce06fe0f638f5c19a85de54"}, - {file = "coverage-7.3.0-cp39-cp39-win32.whl", hash = "sha256:2d22172f938455c156e9af2612650f26cceea47dc86ca048fa4e0b2d21646ad3"}, - {file = "coverage-7.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:60f64e2007c9144375dd0f480a54d6070f00bb1a28f65c408370544091c9bc9e"}, - {file = "coverage-7.3.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:5492a6ce3bdb15c6ad66cb68a0244854d9917478877a25671d70378bdc8562d0"}, - {file = "coverage-7.3.0.tar.gz", hash = "sha256:49dbb19cdcafc130f597d9e04a29d0a032ceedf729e41b181f51cd170e6ee865"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, + {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, + {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, + {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, + {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, + {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, + {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, ] -[package.extras] -toml = ["tomli"] +[package.dependencies] +pycparser = "*" [[package]] -name = "flake8" -version = "6.1.0" -description = "the modular source code checker: pep8 pyflakes and co" +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" optional = false -python-versions = ">=3.8.1" +python-versions = ">=3.7" files = [ - {file = "flake8-6.1.0-py2.py3-none-any.whl", hash = "sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"}, - {file = "flake8-6.1.0.tar.gz", hash = "sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23"}, + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] [package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.11.0,<2.12.0" -pyflakes = ">=3.1.0,<3.2.0" +colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] -name = "idna" -version = "3.2" -description = "Internationalized Domain Names in Applications (IDNA)" +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." optional = false -python-versions = ">=3.5" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ - {file = "idna-3.2-py3-none-any.whl", hash = "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a"}, - {file = "idna-3.2.tar.gz", hash = "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"}, + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] [[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" optional = false -python-versions = ">=3.6" +python-versions = ">=3.5" files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] [[package]] -name = "multidict" -version = "6.0.4" -description = "multidict implementation" +name = "exceptiongroup" +version = "1.2.0" +description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, - {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, - {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, - {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, - {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, - {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, - {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, - {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, - {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, - {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, - {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, - {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, - {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, -] - -[[package]] -name = "mypy" -version = "1.5.1" -description = "Optional static typing for Python" + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "flasgger" +version = "0.9.7.1" +description = "Extract swagger specs from your flask project" optional = false -python-versions = ">=3.8" +python-versions = "*" +files = [ + {file = "flasgger-0.9.7.1.tar.gz", hash = "sha256:ca098e10bfbb12f047acc6299cc70a33851943a746e550d86e65e60d4df245fb"}, +] + +[package.dependencies] +Flask = ">=0.10" +jsonschema = ">=3.0.1" +mistune = "*" +packaging = "*" +PyYAML = ">=3.0" +six = ">=1.10.0" + +[[package]] +name = "flask" +version = "2.1.3" +description = "A simple framework for building complex web applications." +optional = false +python-versions = ">=3.7" files = [ - {file = "mypy-1.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f33592ddf9655a4894aef22d134de7393e95fcbdc2d15c1ab65828eee5c66c70"}, - {file = "mypy-1.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:258b22210a4a258ccd077426c7a181d789d1121aca6db73a83f79372f5569ae0"}, - {file = "mypy-1.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9ec1f695f0c25986e6f7f8778e5ce61659063268836a38c951200c57479cc12"}, - {file = "mypy-1.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:abed92d9c8f08643c7d831300b739562b0a6c9fcb028d211134fc9ab20ccad5d"}, - {file = "mypy-1.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:a156e6390944c265eb56afa67c74c0636f10283429171018446b732f1a05af25"}, - {file = "mypy-1.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ac9c21bfe7bc9f7f1b6fae441746e6a106e48fc9de530dea29e8cd37a2c0cc4"}, - {file = "mypy-1.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51cb1323064b1099e177098cb939eab2da42fea5d818d40113957ec954fc85f4"}, - {file = "mypy-1.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:596fae69f2bfcb7305808c75c00f81fe2829b6236eadda536f00610ac5ec2243"}, - {file = "mypy-1.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:32cb59609b0534f0bd67faebb6e022fe534bdb0e2ecab4290d683d248be1b275"}, - {file = "mypy-1.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:159aa9acb16086b79bbb0016145034a1a05360626046a929f84579ce1666b315"}, - {file = "mypy-1.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f6b0e77db9ff4fda74de7df13f30016a0a663928d669c9f2c057048ba44f09bb"}, - {file = "mypy-1.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:26f71b535dfc158a71264e6dc805a9f8d2e60b67215ca0bfa26e2e1aa4d4d373"}, - {file = "mypy-1.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fc3a600f749b1008cc75e02b6fb3d4db8dbcca2d733030fe7a3b3502902f161"}, - {file = "mypy-1.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:26fb32e4d4afa205b24bf645eddfbb36a1e17e995c5c99d6d00edb24b693406a"}, - {file = "mypy-1.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:82cb6193de9bbb3844bab4c7cf80e6227d5225cc7625b068a06d005d861ad5f1"}, - {file = "mypy-1.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4a465ea2ca12804d5b34bb056be3a29dc47aea5973b892d0417c6a10a40b2d65"}, - {file = "mypy-1.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9fece120dbb041771a63eb95e4896791386fe287fefb2837258925b8326d6160"}, - {file = "mypy-1.5.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d28ddc3e3dfeab553e743e532fb95b4e6afad51d4706dd22f28e1e5e664828d2"}, - {file = "mypy-1.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:57b10c56016adce71fba6bc6e9fd45d8083f74361f629390c556738565af8eeb"}, - {file = "mypy-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:ff0cedc84184115202475bbb46dd99f8dcb87fe24d5d0ddfc0fe6b8575c88d2f"}, - {file = "mypy-1.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8f772942d372c8cbac575be99f9cc9d9fb3bd95c8bc2de6c01411e2c84ebca8a"}, - {file = "mypy-1.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5d627124700b92b6bbaa99f27cbe615c8ea7b3402960f6372ea7d65faf376c14"}, - {file = "mypy-1.5.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:361da43c4f5a96173220eb53340ace68cda81845cd88218f8862dfb0adc8cddb"}, - {file = "mypy-1.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:330857f9507c24de5c5724235e66858f8364a0693894342485e543f5b07c8693"}, - {file = "mypy-1.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:c543214ffdd422623e9fedd0869166c2f16affe4ba37463975043ef7d2ea8770"}, - {file = "mypy-1.5.1-py3-none-any.whl", hash = "sha256:f757063a83970d67c444f6e01d9550a7402322af3557ce7630d3c957386fa8f5"}, - {file = "mypy-1.5.1.tar.gz", hash = "sha256:b031b9601f1060bf1281feab89697324726ba0c0bae9d7cd7ab4b690940f0b92"}, + {file = "Flask-2.1.3-py3-none-any.whl", hash = "sha256:9013281a7402ad527f8fd56375164f3aa021ecfaff89bfe3825346c24f87e04c"}, + {file = "Flask-2.1.3.tar.gz", hash = "sha256:15972e5017df0575c3d6c090ba168b6db90259e620ac8d7ea813a396bad5b6cb"}, ] [package.dependencies] -mypy-extensions = ">=1.0.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=4.1.0" +click = ">=8.0" +importlib-metadata = {version = ">=3.6.0", markers = "python_version < \"3.10\""} +itsdangerous = ">=2.0" +Jinja2 = ">=3.0" +Werkzeug = ">=2.0" [package.extras] -dmypy = ["psutil (>=4.0)"] -install-types = ["pip"] -reports = ["lxml"] +async = ["asgiref (>=3.2)"] +dotenv = ["python-dotenv"] [[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." +name = "greenlet" +version = "2.0.2" +description = "Lightweight in-process concurrent programming" optional = false -python-versions = ">=3.5" +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, + {file = "greenlet-2.0.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:bdfea8c661e80d3c1c99ad7c3ff74e6e87184895bbaca6ee8cc61209f8b9b85d"}, + {file = "greenlet-2.0.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:9d14b83fab60d5e8abe587d51c75b252bcc21683f24699ada8fb275d7712f5a9"}, + {file = "greenlet-2.0.2-cp27-cp27m-win32.whl", hash = "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74"}, + {file = "greenlet-2.0.2-cp27-cp27m-win_amd64.whl", hash = "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343"}, + {file = "greenlet-2.0.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae"}, + {file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d967650d3f56af314b72df7089d96cda1083a7fc2da05b375d2bc48c82ab3f3c"}, + {file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df"}, + {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088"}, + {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb"}, + {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d75209eed723105f9596807495d58d10b3470fa6732dd6756595e89925ce2470"}, + {file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a51c9751078733d88e013587b108f1b7a1fb106d402fb390740f002b6f6551a"}, + {file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91"}, + {file = "greenlet-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645"}, + {file = "greenlet-2.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c"}, + {file = "greenlet-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d4606a527e30548153be1a9f155f4e283d109ffba663a15856089fb55f933e47"}, + {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca"}, + {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0"}, + {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2"}, + {file = "greenlet-2.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:eff4eb9b7eb3e4d0cae3d28c283dc16d9bed6b193c2e1ace3ed86ce48ea8df19"}, + {file = "greenlet-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5454276c07d27a740c5892f4907c86327b632127dd9abec42ee62e12427ff7e3"}, + {file = "greenlet-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:7cafd1208fdbe93b67c7086876f061f660cfddc44f404279c1585bbf3cdc64c5"}, + {file = "greenlet-2.0.2-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:910841381caba4f744a44bf81bfd573c94e10b3045ee00de0cbf436fe50673a6"}, + {file = "greenlet-2.0.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:18a7f18b82b52ee85322d7a7874e676f34ab319b9f8cce5de06067384aa8ff43"}, + {file = "greenlet-2.0.2-cp35-cp35m-win32.whl", hash = "sha256:03a8f4f3430c3b3ff8d10a2a86028c660355ab637cee9333d63d66b56f09d52a"}, + {file = "greenlet-2.0.2-cp35-cp35m-win_amd64.whl", hash = "sha256:4b58adb399c4d61d912c4c331984d60eb66565175cdf4a34792cd9600f21b394"}, + {file = "greenlet-2.0.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:703f18f3fda276b9a916f0934d2fb6d989bf0b4fb5a64825260eb9bfd52d78f0"}, + {file = "greenlet-2.0.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:32e5b64b148966d9cccc2c8d35a671409e45f195864560829f395a54226408d3"}, + {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dd11f291565a81d71dab10b7033395b7a3a5456e637cf997a6f33ebdf06f8db"}, + {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0f72c9ddb8cd28532185f54cc1453f2c16fb417a08b53a855c4e6a418edd099"}, + {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd021c754b162c0fb55ad5d6b9d960db667faad0fa2ff25bb6e1301b0b6e6a75"}, + {file = "greenlet-2.0.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:3c9b12575734155d0c09d6c3e10dbd81665d5c18e1a7c6597df72fd05990c8cf"}, + {file = "greenlet-2.0.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b9ec052b06a0524f0e35bd8790686a1da006bd911dd1ef7d50b77bfbad74e292"}, + {file = "greenlet-2.0.2-cp36-cp36m-win32.whl", hash = "sha256:dbfcfc0218093a19c252ca8eb9aee3d29cfdcb586df21049b9d777fd32c14fd9"}, + {file = "greenlet-2.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:9f35ec95538f50292f6d8f2c9c9f8a3c6540bbfec21c9e5b4b751e0a7c20864f"}, + {file = "greenlet-2.0.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:d5508f0b173e6aa47273bdc0a0b5ba055b59662ba7c7ee5119528f466585526b"}, + {file = "greenlet-2.0.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:f82d4d717d8ef19188687aa32b8363e96062911e63ba22a0cff7802a8e58e5f1"}, + {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9c59a2120b55788e800d82dfa99b9e156ff8f2227f07c5e3012a45a399620b7"}, + {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2780572ec463d44c1d3ae850239508dbeb9fed38e294c68d19a24d925d9223ca"}, + {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:937e9020b514ceedb9c830c55d5c9872abc90f4b5862f89c0887033ae33c6f73"}, + {file = "greenlet-2.0.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:36abbf031e1c0f79dd5d596bfaf8e921c41df2bdf54ee1eed921ce1f52999a86"}, + {file = "greenlet-2.0.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:18e98fb3de7dba1c0a852731c3070cf022d14f0d68b4c87a19cc1016f3bb8b33"}, + {file = "greenlet-2.0.2-cp37-cp37m-win32.whl", hash = "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7"}, + {file = "greenlet-2.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3"}, + {file = "greenlet-2.0.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30"}, + {file = "greenlet-2.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1087300cf9700bbf455b1b97e24db18f2f77b55302a68272c56209d5587c12d1"}, + {file = "greenlet-2.0.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b"}, + {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"}, + {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b"}, + {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acd2162a36d3de67ee896c43effcd5ee3de247eb00354db411feb025aa319857"}, + {file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0bf60faf0bc2468089bdc5edd10555bab6e85152191df713e2ab1fcc86382b5a"}, + {file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a"}, + {file = "greenlet-2.0.2-cp38-cp38-win32.whl", hash = "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249"}, + {file = "greenlet-2.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40"}, + {file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8512a0c38cfd4e66a858ddd1b17705587900dd760c6003998e9472b77b56d417"}, + {file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8"}, + {file = "greenlet-2.0.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6"}, + {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df"}, + {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be4ed120b52ae4d974aa40215fcdfde9194d63541c7ded40ee12eb4dda57b76b"}, + {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94c817e84245513926588caf1152e3b559ff794d505555211ca041f032abbb6b"}, + {file = "greenlet-2.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1a819eef4b0e0b96bb0d98d797bef17dc1b4a10e8d7446be32d1da33e095dbb8"}, + {file = "greenlet-2.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7efde645ca1cc441d6dc4b48c0f7101e8d86b54c8530141b09fd31cef5149ec9"}, + {file = "greenlet-2.0.2-cp39-cp39-win32.whl", hash = "sha256:ea9872c80c132f4663822dd2a08d404073a5a9b5ba6155bea72fb2a79d1093b5"}, + {file = "greenlet-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:db1a39669102a1d8d12b57de2bb7e2ec9066a6f2b3da35ae511ff93b01b5d564"}, + {file = "greenlet-2.0.2.tar.gz", hash = "sha256:e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0"}, ] +[package.extras] +docs = ["Sphinx", "docutils (<0.18)"] +test = ["objgraph", "psutil"] + [[package]] -name = "pycodestyle" -version = "2.11.0" -description = "Python style guide checker" +name = "greenlet" +version = "3.0.1" +description = "Lightweight in-process concurrent programming" optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" +files = [ + {file = "greenlet-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f89e21afe925fcfa655965ca8ea10f24773a1791400989ff32f467badfe4a064"}, + {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28e89e232c7593d33cac35425b58950789962011cc274aa43ef8865f2e11f46d"}, + {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8ba29306c5de7717b5761b9ea74f9c72b9e2b834e24aa984da99cbfc70157fd"}, + {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19bbdf1cce0346ef7341705d71e2ecf6f41a35c311137f29b8a2dc2341374565"}, + {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:599daf06ea59bfedbec564b1692b0166a0045f32b6f0933b0dd4df59a854caf2"}, + {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b641161c302efbb860ae6b081f406839a8b7d5573f20a455539823802c655f63"}, + {file = "greenlet-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d57e20ba591727da0c230ab2c3f200ac9d6d333860d85348816e1dca4cc4792e"}, + {file = "greenlet-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5805e71e5b570d490938d55552f5a9e10f477c19400c38bf1d5190d760691846"}, + {file = "greenlet-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:52e93b28db27ae7d208748f45d2db8a7b6a380e0d703f099c949d0f0d80b70e9"}, + {file = "greenlet-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f7bfb769f7efa0eefcd039dd19d843a4fbfbac52f1878b1da2ed5793ec9b1a65"}, + {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e6c7db42638dc45cf2e13c73be16bf83179f7859b07cfc139518941320be96"}, + {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1757936efea16e3f03db20efd0cd50a1c86b06734f9f7338a90c4ba85ec2ad5a"}, + {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19075157a10055759066854a973b3d1325d964d498a805bb68a1f9af4aaef8ec"}, + {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9d21aaa84557d64209af04ff48e0ad5e28c5cca67ce43444e939579d085da72"}, + {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2847e5d7beedb8d614186962c3d774d40d3374d580d2cbdab7f184580a39d234"}, + {file = "greenlet-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:97e7ac860d64e2dcba5c5944cfc8fa9ea185cd84061c623536154d5a89237884"}, + {file = "greenlet-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b2c02d2ad98116e914d4f3155ffc905fd0c025d901ead3f6ed07385e19122c94"}, + {file = "greenlet-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:22f79120a24aeeae2b4471c711dcf4f8c736a2bb2fabad2a67ac9a55ea72523c"}, + {file = "greenlet-3.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:100f78a29707ca1525ea47388cec8a049405147719f47ebf3895e7509c6446aa"}, + {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60d5772e8195f4e9ebf74046a9121bbb90090f6550f81d8956a05387ba139353"}, + {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:daa7197b43c707462f06d2c693ffdbb5991cbb8b80b5b984007de431493a319c"}, + {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea6b8aa9e08eea388c5f7a276fabb1d4b6b9d6e4ceb12cc477c3d352001768a9"}, + {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d11ebbd679e927593978aa44c10fc2092bc454b7d13fdc958d3e9d508aba7d0"}, + {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dbd4c177afb8a8d9ba348d925b0b67246147af806f0b104af4d24f144d461cd5"}, + {file = "greenlet-3.0.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20107edf7c2c3644c67c12205dc60b1bb11d26b2610b276f97d666110d1b511d"}, + {file = "greenlet-3.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8bef097455dea90ffe855286926ae02d8faa335ed8e4067326257cb571fc1445"}, + {file = "greenlet-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:b2d3337dcfaa99698aa2377c81c9ca72fcd89c07e7eb62ece3f23a3fe89b2ce4"}, + {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80ac992f25d10aaebe1ee15df45ca0d7571d0f70b645c08ec68733fb7a020206"}, + {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:337322096d92808f76ad26061a8f5fccb22b0809bea39212cd6c406f6a7060d2"}, + {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9934adbd0f6e476f0ecff3c94626529f344f57b38c9a541f87098710b18af0a"}, + {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc4d815b794fd8868c4d67602692c21bf5293a75e4b607bb92a11e821e2b859a"}, + {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41bdeeb552d814bcd7fb52172b304898a35818107cc8778b5101423c9017b3de"}, + {file = "greenlet-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6e6061bf1e9565c29002e3c601cf68569c450be7fc3f7336671af7ddb4657166"}, + {file = "greenlet-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:fa24255ae3c0ab67e613556375a4341af04a084bd58764731972bcbc8baeba36"}, + {file = "greenlet-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:b489c36d1327868d207002391f662a1d163bdc8daf10ab2e5f6e41b9b96de3b1"}, + {file = "greenlet-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f33f3258aae89da191c6ebaa3bc517c6c4cbc9b9f689e5d8452f7aedbb913fa8"}, + {file = "greenlet-3.0.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:d2905ce1df400360463c772b55d8e2518d0e488a87cdea13dd2c71dcb2a1fa16"}, + {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a02d259510b3630f330c86557331a3b0e0c79dac3d166e449a39363beaae174"}, + {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55d62807f1c5a1682075c62436702aaba941daa316e9161e4b6ccebbbf38bda3"}, + {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3fcc780ae8edbb1d050d920ab44790201f027d59fdbd21362340a85c79066a74"}, + {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4eddd98afc726f8aee1948858aed9e6feeb1758889dfd869072d4465973f6bfd"}, + {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eabe7090db68c981fca689299c2d116400b553f4b713266b130cfc9e2aa9c5a9"}, + {file = "greenlet-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f2f6d303f3dee132b322a14cd8765287b8f86cdc10d2cb6a6fae234ea488888e"}, + {file = "greenlet-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d923ff276f1c1f9680d32832f8d6c040fe9306cbfb5d161b0911e9634be9ef0a"}, + {file = "greenlet-3.0.1-cp38-cp38-win32.whl", hash = "sha256:0b6f9f8ca7093fd4433472fd99b5650f8a26dcd8ba410e14094c1e44cd3ceddd"}, + {file = "greenlet-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:990066bff27c4fcf3b69382b86f4c99b3652bab2a7e685d968cd4d0cfc6f67c6"}, + {file = "greenlet-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ce85c43ae54845272f6f9cd8320d034d7a946e9773c693b27d620edec825e376"}, + {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89ee2e967bd7ff85d84a2de09df10e021c9b38c7d91dead95b406ed6350c6997"}, + {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87c8ceb0cf8a5a51b8008b643844b7f4a8264a2c13fcbcd8a8316161725383fe"}, + {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6a8c9d4f8692917a3dc7eb25a6fb337bff86909febe2f793ec1928cd97bedfc"}, + {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fbc5b8f3dfe24784cee8ce0be3da2d8a79e46a276593db6868382d9c50d97b1"}, + {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85d2b77e7c9382f004b41d9c72c85537fac834fb141b0296942d52bf03fe4a3d"}, + {file = "greenlet-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:696d8e7d82398e810f2b3622b24e87906763b6ebfd90e361e88eb85b0e554dc8"}, + {file = "greenlet-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:329c5a2e5a0ee942f2992c5e3ff40be03e75f745f48847f118a3cfece7a28546"}, + {file = "greenlet-3.0.1-cp39-cp39-win32.whl", hash = "sha256:cf868e08690cb89360eebc73ba4be7fb461cfbc6168dd88e2fbbe6f31812cd57"}, + {file = "greenlet-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:ac4a39d1abae48184d420aa8e5e63efd1b75c8444dd95daa3e03f6c6310e9619"}, + {file = "greenlet-3.0.1.tar.gz", hash = "sha256:816bd9488a94cba78d93e1abb58000e8266fa9cc2aa9ccdd6eb0696acb24005b"}, +] + +[package.extras] +docs = ["Sphinx"] +test = ["objgraph", "psutil"] + +[[package]] +name = "httpbin" +version = "0.10.1" +description = "HTTP Request and Response Service" +optional = false +python-versions = ">=3.7" files = [ - {file = "pycodestyle-2.11.0-py2.py3-none-any.whl", hash = "sha256:5d1013ba8dc7895b548be5afb05740ca82454fd899971563d2ef625d090326f8"}, - {file = "pycodestyle-2.11.0.tar.gz", hash = "sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0"}, + {file = "httpbin-0.10.1-py2.py3-none-any.whl", hash = "sha256:c81ec67dbc91062b0f6ea296795a29bf1092d014b201097ebc417439c2a0054e"}, + {file = "httpbin-0.10.1.tar.gz", hash = "sha256:7b8596beb0e75a7b653c39d1f3cf263d6d5c476d29e1df6f7bb2b70bf9f06a3d"}, +] + +[package.dependencies] +brotlicffi = "*" +decorator = "*" +flasgger = "*" +Flask = "*" +greenlet = [ + {version = "<3.0", markers = "python_version < \"3.12\""}, + {version = ">=3.0.0a1", markers = "python_version >= \"3.12\""}, ] +six = "*" +werkzeug = ">=0.14.1" + +[package.extras] +mainapp = ["gevent", "gunicorn"] +test = ["pytest", "tox"] [[package]] -name = "pyflakes" -version = "3.1.0" -description = "passive checker of Python programs" +name = "importlib-metadata" +version = "7.0.1" +description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"}, - {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"}, + {file = "importlib_metadata-7.0.1-py3-none-any.whl", hash = "sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e"}, + {file = "importlib_metadata-7.0.1.tar.gz", hash = "sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc"}, ] +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + [[package]] -name = "pyyaml" -version = "5.4.1" -description = "YAML parser and emitter for Python" +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -files = [ - {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"}, - {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"}, - {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"}, - {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"}, - {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"}, - {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"}, - {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"}, - {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"}, - {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"}, - {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"}, - {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"}, - {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"}, - {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"}, - {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"}, - {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"}, - {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"}, - {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"}, - {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"}, - {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"}, - {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"}, - {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"}, - {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"}, - {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"}, - {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"}, - {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"}, - {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"}, - {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"}, - {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, - {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, -] - -[[package]] -name = "requests" -version = "2.31.0" -description = "Python HTTP for Humans." +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "itsdangerous" +version = "2.1.2" +description = "Safely pass data to untrusted environments and back." optional = false python-versions = ">=3.7" files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"}, + {file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"}, +] + +[[package]] +name = "jinja2" +version = "3.1.3" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, + {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, ] [package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" +MarkupSafe = ">=2.0" [package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +i18n = ["Babel (>=2.7)"] [[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" +name = "jsonschema" +version = "4.20.0" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema-4.20.0-py3-none-any.whl", hash = "sha256:ed6231f0429ecf966f5bc8dfef245998220549cbbcf140f913b7464c52c3b6b3"}, + {file = "jsonschema-4.20.0.tar.gz", hash = "sha256:4f614fd46d8d61258610998997743ec5492a648b33cf478c1ddc23ed4598a5fa"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] + +[[package]] +name = "jsonschema-specifications" +version = "2023.11.2" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema_specifications-2023.11.2-py3-none-any.whl", hash = "sha256:e74ba7c0a65e8cb49dc26837d6cfe576557084a8b423ed16a420984228104f93"}, + {file = "jsonschema_specifications-2023.11.2.tar.gz", hash = "sha256:9472fc4fea474cd74bea4a2b190daeccb5a9e4db2ea80efcf7a1b582fc9a81b8"}, +] + +[package.dependencies] +referencing = ">=0.31.0" + +[[package]] +name = "markupsafe" +version = "2.1.3" +description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.7" files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, + {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, ] [[package]] -name = "types-pyyaml" -version = "6.0.12.11" -description = "Typing stubs for PyYAML" +name = "mistune" +version = "3.0.2" +description = "A sane and fast Markdown parser with useful plugins and renderers" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "types-PyYAML-6.0.12.11.tar.gz", hash = "sha256:7d340b19ca28cddfdba438ee638cd4084bde213e501a3978738543e27094775b"}, - {file = "types_PyYAML-6.0.12.11-py3-none-any.whl", hash = "sha256:a461508f3096d1d5810ec5ab95d7eeecb651f3a15b71959999988942063bf01d"}, + {file = "mistune-3.0.2-py3-none-any.whl", hash = "sha256:71481854c30fdbc938963d3605b72501f5c10a9320ecd412c121c163a1c7d205"}, + {file = "mistune-3.0.2.tar.gz", hash = "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8"}, ] [[package]] -name = "types-requests" -version = "2.31.0.2" -description = "Typing stubs for requests" +name = "packaging" +version = "23.2" +description = "Core utilities for Python packages" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "types-requests-2.31.0.2.tar.gz", hash = "sha256:6aa3f7faf0ea52d728bb18c0a0d1522d9bfd8c72d26ff6f61bfc3d06a411cf40"}, - {file = "types_requests-2.31.0.2-py3-none-any.whl", hash = "sha256:56d181c85b5925cbc59f4489a57e72a8b2166f18273fd8ba7b6fe0c0b986f12a"}, + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] -[package.dependencies] -types-urllib3 = "*" +[[package]] +name = "pluggy" +version = "1.4.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] [[package]] -name = "types-urllib3" -version = "1.26.25.14" -description = "Typing stubs for urllib3" +name = "pycparser" +version = "2.21" +description = "C parser in Python" optional = false -python-versions = "*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ - {file = "types-urllib3-1.26.25.14.tar.gz", hash = "sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f"}, - {file = "types_urllib3-1.26.25.14-py3-none-any.whl", hash = "sha256:9683bbb7fb72e32bfe9d2be6e04875fbe1b3eeec3cbb4ea231435aa7fd6b4f0e"}, + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] [[package]] -name = "typing-extensions" -version = "4.7.1" -description = "Backported and Experimental Type Hints for Python 3.7+" +name = "pytest" +version = "7.4.4" +description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" files = [ - {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, - {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, ] +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + [[package]] -name = "urllib3" -version = "1.26.6" -description = "HTTP library with thread-safe connection pooling, file post, and more." +name = "pytest-httpbin" +version = "2.0.0" +description = "Easily test your HTTP library against a local copy of httpbin" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +python-versions = ">=3.7" files = [ - {file = "urllib3-1.26.6-py2.py3-none-any.whl", hash = "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4"}, - {file = "urllib3-1.26.6.tar.gz", hash = "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"}, + {file = "pytest-httpbin-2.0.0.tar.gz", hash = "sha256:3e739cad9b8f8df58952df7329d9295fe17449d3a647f49c4ce634fd81d71b8e"}, + {file = "pytest_httpbin-2.0.0-py2.py3-none-any.whl", hash = "sha256:d977f8095796e27a45911bbafa3587c081c9025e060e2fdb559794db2d45e82d"}, ] +[package.dependencies] +httpbin = "*" + [package.extras] -brotli = ["brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +test = ["pytest", "requests", "werkzeug (<2.1.0)"] + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] [[package]] -name = "vcrpy" -version = "5.1.0" -description = "Automatically mock your HTTP interactions to simplify and speed up testing" +name = "referencing" +version = "0.33.0" +description = "JSON Referencing + Python" optional = false python-versions = ">=3.8" files = [ - {file = "vcrpy-5.1.0-py2.py3-none-any.whl", hash = "sha256:605e7b7a63dcd940db1df3ab2697ca7faf0e835c0852882142bafb19649d599e"}, - {file = "vcrpy-5.1.0.tar.gz", hash = "sha256:bbf1532f2618a04f11bce2a99af3a9647a32c880957293ff91e0a5f187b6b3d2"}, + {file = "referencing-0.33.0-py3-none-any.whl", hash = "sha256:39240f2ecc770258f28b642dd47fd74bc8b02484de54e1882b74b35ebd779bd5"}, + {file = "referencing-0.33.0.tar.gz", hash = "sha256:c775fedf74bc0f9189c2a3be1c12fd03e8c23f4d371dce795df44e06c5b412f7"}, ] [package.dependencies] -PyYAML = "*" -urllib3 = {version = "<2", markers = "python_version < \"3.10\""} -wrapt = "*" -yarl = "*" - -[[package]] -name = "wrapt" -version = "1.15.0" -description = "Module for decorators, wrappers and monkey patching." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -files = [ - {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, - {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, - {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, - {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, - {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, - {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, - {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, - {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, - {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, - {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, - {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, - {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, - {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, - {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, - {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, - {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, - {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, - {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, - {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, -] - -[[package]] -name = "yarl" -version = "1.9.2" -description = "Yet another URL library" +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + +[[package]] +name = "rpds-py" +version = "0.18.0" +description = "Python bindings to Rust's persistent data structures (rpds)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "rpds_py-0.18.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5b4e7d8d6c9b2e8ee2d55c90b59c707ca59bc30058269b3db7b1f8df5763557e"}, + {file = "rpds_py-0.18.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c463ed05f9dfb9baebef68048aed8dcdc94411e4bf3d33a39ba97e271624f8f7"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d62dec4976954a23d7f91f2f4530852b0c7608116c257833922a896101336c51"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd18772815d5f008fa03d2b9a681ae38d5ae9f0e599f7dda233c439fcaa00d40"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:923d39efa3cfb7279a0327e337a7958bff00cc447fd07a25cddb0a1cc9a6d2da"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39514da80f971362f9267c600b6d459bfbbc549cffc2cef8e47474fddc9b45b1"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a34d557a42aa28bd5c48a023c570219ba2593bcbbb8dc1b98d8cf5d529ab1434"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:93df1de2f7f7239dc9cc5a4a12408ee1598725036bd2dedadc14d94525192fc3"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:34b18ba135c687f4dac449aa5157d36e2cbb7c03cbea4ddbd88604e076aa836e"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0b5dcf9193625afd8ecc92312d6ed78781c46ecbf39af9ad4681fc9f464af88"}, + {file = "rpds_py-0.18.0-cp310-none-win32.whl", hash = "sha256:c4325ff0442a12113a6379af66978c3fe562f846763287ef66bdc1d57925d337"}, + {file = "rpds_py-0.18.0-cp310-none-win_amd64.whl", hash = "sha256:7223a2a5fe0d217e60a60cdae28d6949140dde9c3bcc714063c5b463065e3d66"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d68c93e381010662ab873fea609bf6c0f428b6d0bb00f2c6939782e0818d37bf"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b34b7aa8b261c1dbf7720b5d6f01f38243e9b9daf7e6b8bc1fd4657000062f2c"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e6d75ab12b0bbab7215e5d40f1e5b738aa539598db27ef83b2ec46747df90e1"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aec493917dd45e3c69d00a8874e7cbed844efd935595ef78a0f25f14312e33c6"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:661d25cbffaf8cc42e971dd570d87cb29a665f49f4abe1f9e76be9a5182c4688"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1df3659d26f539ac74fb3b0c481cdf9d725386e3552c6fa2974f4d33d78e544b"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1ce3ba137ed54f83e56fb983a5859a27d43a40188ba798993812fed73c70836"}, + {file = "rpds_py-0.18.0-cp311-none-win32.whl", hash = "sha256:69e64831e22a6b377772e7fb337533c365085b31619005802a79242fee620bc1"}, + {file = "rpds_py-0.18.0-cp311-none-win_amd64.whl", hash = "sha256:998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7f2facbd386dd60cbbf1a794181e6aa0bd429bd78bfdf775436020172e2a23f0"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d9a5be316c15ffb2b3c405c4ff14448c36b4435be062a7f578ccd8b01f0c4d8"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd5bf1af8efe569654bbef5a3e0a56eca45f87cfcffab31dd8dde70da5982475"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5417558f6887e9b6b65b4527232553c139b57ec42c64570569b155262ac0754f"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:56a737287efecafc16f6d067c2ea0117abadcd078d58721f967952db329a3e5c"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8f03bccbd8586e9dd37219bce4d4e0d3ab492e6b3b533e973fa08a112cb2ffc9"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4457a94da0d5c53dc4b3e4de1158bdab077db23c53232f37a3cb7afdb053a4e3"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ab39c1ba9023914297dd88ec3b3b3c3f33671baeb6acf82ad7ce883f6e8e157"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9d54553c1136b50fd12cc17e5b11ad07374c316df307e4cfd6441bea5fb68496"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0af039631b6de0397ab2ba16eaf2872e9f8fca391b44d3d8cac317860a700a3f"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:84ffab12db93b5f6bad84c712c92060a2d321b35c3c9960b43d08d0f639d60d7"}, + {file = "rpds_py-0.18.0-cp312-none-win32.whl", hash = "sha256:685537e07897f173abcf67258bee3c05c374fa6fff89d4c7e42fb391b0605e98"}, + {file = "rpds_py-0.18.0-cp312-none-win_amd64.whl", hash = "sha256:e003b002ec72c8d5a3e3da2989c7d6065b47d9eaa70cd8808b5384fbb970f4ec"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:08f9ad53c3f31dfb4baa00da22f1e862900f45908383c062c27628754af2e88e"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0013fe6b46aa496a6749c77e00a3eb07952832ad6166bd481c74bda0dcb6d58"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32a92116d4f2a80b629778280103d2a510a5b3f6314ceccd6e38006b5e92dcb"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e541ec6f2ec456934fd279a3120f856cd0aedd209fc3852eca563f81738f6861"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bed88b9a458e354014d662d47e7a5baafd7ff81c780fd91584a10d6ec842cb73"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2644e47de560eb7bd55c20fc59f6daa04682655c58d08185a9b95c1970fa1e07"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e8916ae4c720529e18afa0b879473049e95949bf97042e938530e072fde061d"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:465a3eb5659338cf2a9243e50ad9b2296fa15061736d6e26240e713522b6235c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ea7d4a99f3b38c37eac212dbd6ec42b7a5ec51e2c74b5d3223e43c811609e65f"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:67071a6171e92b6da534b8ae326505f7c18022c6f19072a81dcf40db2638767c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:41ef53e7c58aa4ef281da975f62c258950f54b76ec8e45941e93a3d1d8580594"}, + {file = "rpds_py-0.18.0-cp38-none-win32.whl", hash = "sha256:fdea4952db2793c4ad0bdccd27c1d8fdd1423a92f04598bc39425bcc2b8ee46e"}, + {file = "rpds_py-0.18.0-cp38-none-win_amd64.whl", hash = "sha256:7cd863afe7336c62ec78d7d1349a2f34c007a3cc6c2369d667c65aeec412a5b1"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5307def11a35f5ae4581a0b658b0af8178c65c530e94893345bebf41cc139d33"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77f195baa60a54ef9d2de16fbbfd3ff8b04edc0c0140a761b56c267ac11aa467"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39f5441553f1c2aed4de4377178ad8ff8f9d733723d6c66d983d75341de265ab"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a00312dea9310d4cb7dbd7787e722d2e86a95c2db92fbd7d0155f97127bcb40"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f2fc11e8fe034ee3c34d316d0ad8808f45bc3b9ce5857ff29d513f3ff2923a1"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:586f8204935b9ec884500498ccc91aa869fc652c40c093bd9e1471fbcc25c022"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddc2f4dfd396c7bfa18e6ce371cba60e4cf9d2e5cdb71376aa2da264605b60b9"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ddcba87675b6d509139d1b521e0c8250e967e63b5909a7e8f8944d0f90ff36f"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7bd339195d84439cbe5771546fe8a4e8a7a045417d8f9de9a368c434e42a721e"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d7c36232a90d4755b720fbd76739d8891732b18cf240a9c645d75f00639a9024"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6b0817e34942b2ca527b0e9298373e7cc75f429e8da2055607f4931fded23e20"}, + {file = "rpds_py-0.18.0-cp39-none-win32.whl", hash = "sha256:99f70b740dc04d09e6b2699b675874367885217a2e9f782bdf5395632ac663b7"}, + {file = "rpds_py-0.18.0-cp39-none-win_amd64.whl", hash = "sha256:6ef687afab047554a2d366e112dd187b62d261d49eb79b77e386f94644363294"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ad36cfb355e24f1bd37cac88c112cd7730873f20fb0bdaf8ba59eedf8216079f"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:36b3ee798c58ace201289024b52788161e1ea133e4ac93fba7d49da5fec0ef9e"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8a2f084546cc59ea99fda8e070be2fd140c3092dc11524a71aa8f0f3d5a55ca"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e4461d0f003a0aa9be2bdd1b798a041f177189c1a0f7619fe8c95ad08d9a45d7"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8db715ebe3bb7d86d77ac1826f7d67ec11a70dbd2376b7cc214199360517b641"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793968759cd0d96cac1e367afd70c235867831983f876a53389ad869b043c948"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66e6a3af5a75363d2c9a48b07cb27c4ea542938b1a2e93b15a503cdfa8490795"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ef0befbb5d79cf32d0266f5cff01545602344eda89480e1dd88aca964260b18"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d4acf42190d449d5e89654d5c1ed3a4f17925eec71f05e2a41414689cda02d1"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a5f446dd5055667aabaee78487f2b5ab72e244f9bc0b2ffebfeec79051679984"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9dbbeb27f4e70bfd9eec1be5477517365afe05a9b2c441a0b21929ee61048124"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:22806714311a69fd0af9b35b7be97c18a0fc2826e6827dbb3a8c94eac6cf7eeb"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b34ae4636dfc4e76a438ab826a0d1eed2589ca7d9a1b2d5bb546978ac6485461"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c8370641f1a7f0e0669ddccca22f1da893cef7628396431eb445d46d893e5cd"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c8362467a0fdeccd47935f22c256bec5e6abe543bf0d66e3d3d57a8fb5731863"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11a8c85ef4a07a7638180bf04fe189d12757c696eb41f310d2426895356dcf05"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b316144e85316da2723f9d8dc75bada12fa58489a527091fa1d5a612643d1a0e"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf1ea2e34868f6fbf070e1af291c8180480310173de0b0c43fc38a02929fc0e3"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e546e768d08ad55b20b11dbb78a745151acbd938f8f00d0cfbabe8b0199b9880"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4901165d170a5fde6f589acb90a6b33629ad1ec976d4529e769c6f3d885e3e80"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:618a3d6cae6ef8ec88bb76dd80b83cfe415ad4f1d942ca2a903bf6b6ff97a2da"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ed4eb745efbff0a8e9587d22a84be94a5eb7d2d99c02dacf7bd0911713ed14dd"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c81e5f372cd0dc5dc4809553d34f832f60a46034a5f187756d9b90586c2c307"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:43fbac5f22e25bee1d482c97474f930a353542855f05c1161fd804c9dc74a09d"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d7faa6f14017c0b1e69f5e2c357b998731ea75a442ab3841c0dbbbfe902d2c4"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:08231ac30a842bd04daabc4d71fddd7e6d26189406d5a69535638e4dcb88fe76"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:044a3e61a7c2dafacae99d1e722cc2d4c05280790ec5a05031b3876809d89a5c"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f26b5bd1079acdb0c7a5645e350fe54d16b17bfc5e71f371c449383d3342e17"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:482103aed1dfe2f3b71a58eff35ba105289b8d862551ea576bd15479aba01f66"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1374f4129f9bcca53a1bba0bb86bf78325a0374577cf7e9e4cd046b1e6f20e24"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:635dc434ff724b178cb192c70016cc0ad25a275228f749ee0daf0eddbc8183b1"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:bc362ee4e314870a70f4ae88772d72d877246537d9f8cb8f7eacf10884862432"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4832d7d380477521a8c1644bbab6588dfedea5e30a7d967b5fb75977c45fd77f"}, + {file = "rpds_py-0.18.0.tar.gz", hash = "sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d"}, +] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" optional = false python-versions = ">=3.7" files = [ - {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, - {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, - {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, - {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, - {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, - {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, - {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, - {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, - {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, - {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, - {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, - {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, - {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, - {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, - {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" +[[package]] +name = "werkzeug" +version = "2.0.3" +description = "The comprehensive WSGI web application library." +optional = false +python-versions = ">=3.6" +files = [ + {file = "Werkzeug-2.0.3-py3-none-any.whl", hash = "sha256:1421ebfc7648a39a5c58c601b154165d05cf47a3cd0ccb70857cbdacf6c8f2b8"}, + {file = "Werkzeug-2.0.3.tar.gz", hash = "sha256:b863f8ff057c522164b6067c9e28b041161b4be5ba4d0daceeaa50a163822d3c"}, +] + +[package.extras] +watchdog = ["watchdog"] + +[[package]] +name = "zipp" +version = "3.17.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "56d28407f6665099eeac3fa2b7ef901426d2f4b1e00829036a50e0ff19c1d824" +content-hash = "74bf4101b1090102829a63c72a3ec39004fb5e87d77ab8b31270fc6152c82f0d" diff --git a/proxy/pyproject.toml b/proxy/pyproject.toml index 22b8961f4..0ebe43d44 100644 --- a/proxy/pyproject.toml +++ b/proxy/pyproject.toml @@ -8,13 +8,9 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.9" -pyyaml = "^5.4.1" -requests = "^2.31.0" [tool.poetry.group.dev.dependencies] -coverage = "^7.3.0" -flake8 = "^6.1.0" -mypy = "^1.5.1" -types-PyYAML = "^6.0.12.11" -types-requests = "^2.31.0.2" -vcrpy = "^5.1.0" +pytest = "^7.4.3" +pytest-httpbin = "^2.0.0" +# needed for httpbin, see https://github.com/psf/httpbin/issues/36 +werkzeug = "<2.1.0" diff --git a/proxy/qubes/securedrop.Proxy b/proxy/qubes/securedrop.Proxy index f8eee7cb2..a3348f16e 100755 --- a/proxy/qubes/securedrop.Proxy +++ b/proxy/qubes/securedrop.Proxy @@ -1 +1 @@ -/usr/bin/sd-proxy /home/user/.securedrop_proxy/sd-proxy.yaml +/usr/bin/securedrop-proxy diff --git a/proxy/securedrop_proxy/__init__.py b/proxy/securedrop_proxy/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/proxy/securedrop_proxy/entrypoint.py b/proxy/securedrop_proxy/entrypoint.py deleted file mode 100755 index 9e881969f..000000000 --- a/proxy/securedrop_proxy/entrypoint.py +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env python3 - -# The sd-proxy RPC script triggered by qubes RPC. - -# This script is executed by `/etc/qubes-rpc/sd-proxy`. It must be -# called with exactly one argument: the path to its config file. See -# the README for configuration options. - -import http -import logging -import os -import platform -import sys -from logging.handlers import SysLogHandler, TimedRotatingFileHandler - -from securedrop_proxy import json, main, proxy -from securedrop_proxy.version import version - -DEFAULT_HOME = os.path.join(os.path.expanduser("~"), ".securedrop_proxy") -LOGLEVEL = os.environ.get("LOGLEVEL", "info").upper() - - -def start() -> None: - """ - Set up a new proxy object with an error handler, configuration that we read - from argv[1], and the original user request from STDIN. - """ - try: - configure_logging() - - logging.debug("Starting SecureDrop Proxy {}".format(version)) - - # path to config file must be at argv[1] - if len(sys.argv) != 2: - raise ValueError("sd-proxy script not called with path to configuration file") - - # read config. `read_conf` will call `p.err_on_done` if there is a config - # problem, and will return a Conf object on success. - conf_path = sys.argv[1] - # a fresh, new proxy object - p = proxy.Proxy(conf_path=conf_path) - - # read user request from STDIN - incoming_lines = [] - for line in sys.stdin: - incoming_lines.append(line) - incoming = "\n".join(incoming_lines) - - main.__main__(incoming, p) - except Exception as e: - response = { - "status": http.HTTPStatus.INTERNAL_SERVER_ERROR, - "body": json.dumps({"error": str(e)}), - } - print(json.dumps(response)) - sys.exit(1) - - -def configure_logging() -> None: - """ - All logging related settings are set up by this function. - """ - home = os.getenv("SECUREDROP_HOME", DEFAULT_HOME) - log_folder = os.path.join(home, "logs") - if not os.path.exists(log_folder): - os.makedirs(log_folder) - - log_file = os.path.join(home, "logs", "proxy.log") - - # set logging format - log_fmt = "%(asctime)s - %(name)s:%(lineno)d(%(funcName)s) %(levelname)s: %(message)s" - formatter = logging.Formatter(log_fmt) - - # define log handlers such as for rotating log files - handler = TimedRotatingFileHandler(log_file) - handler.setFormatter(formatter) - handler.setLevel(logging.DEBUG) - - # For rsyslog handler - if platform.system() != "Linux": # pragma: no cover - syslog_file = "/var/run/syslog" - else: - syslog_file = "/dev/log" - - sysloghandler = SysLogHandler(address=syslog_file) - sysloghandler.setFormatter(formatter) - - # set up primary log - log = logging.getLogger() - log.setLevel(LOGLEVEL) - log.addHandler(handler) - - # add the secondard logger - log.addHandler(sysloghandler) diff --git a/proxy/securedrop_proxy/json.py b/proxy/securedrop_proxy/json.py deleted file mode 100644 index 24babe912..000000000 --- a/proxy/securedrop_proxy/json.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -Wrapper around Python's json to catch duplicate keys (potential JSON injection) - -This was informational finding TOB-SDW-014 in the 2020 audit. -""" - -import json - -dumps = json.dumps - - -def _check(seq): - d = {} - for key, value in seq: - if key in d: - raise ValueError(f"Key '{key}' found twice in JSON object") - d[key] = value - return d - - -def loads(text: str) -> dict: - """ - Turn a string into a JSON object, but reject duplicate keys - """ - return json.loads(text, object_pairs_hook=_check) diff --git a/proxy/securedrop_proxy/main.py b/proxy/securedrop_proxy/main.py deleted file mode 100644 index 040813f1a..000000000 --- a/proxy/securedrop_proxy/main.py +++ /dev/null @@ -1,45 +0,0 @@ -import logging -from typing import Any, Dict - -from securedrop_proxy import json, proxy -from securedrop_proxy.proxy import Proxy - -logger = logging.getLogger(__name__) - - -def __main__(incoming: str, p: Proxy) -> None: - """ - Deserialize incoming request in order to build and send a proxy request. - """ - logging.debug("Creating request to be sent by proxy") - - client_req: Dict[str, Any] = {} - try: - client_req = json.loads(incoming) - except ValueError as e: - logging.error(e) - p.simple_error(400, "Invalid JSON in request") - p.on_done() - return - - req = proxy.Req() - try: - req.method = client_req["method"] - req.path_query = client_req["path_query"] - except KeyError as e: - logging.error(e) - p.simple_error(400, "Missing keys in request") - p.on_done() - - if "headers" in client_req: - req.headers = client_req["headers"] - - if "body" in client_req: - req.body = client_req["body"] - - p.req = req - - if "timeout" in client_req: - p.timeout = client_req["timeout"] - - p.proxy() diff --git a/proxy/securedrop_proxy/proxy.py b/proxy/securedrop_proxy/proxy.py deleted file mode 100644 index b87d43c19..000000000 --- a/proxy/securedrop_proxy/proxy.py +++ /dev/null @@ -1,293 +0,0 @@ -import http -import logging -import os -import posixpath -import subprocess -import sys -import tempfile -import uuid -from typing import IO, Dict, Optional -from urllib.parse import ParseResult, urlparse - -import requests -import yaml - -import securedrop_proxy.version as version -from securedrop_proxy import json - -logger = logging.getLogger(__name__) - - -def is_json_content_type(value: str) -> bool: - """ - Is the value of the content-type header JSON? - - See - """ - return value == "application/json" or value.startswith("application/json;") - - -class Conf: - scheme = "" - host = "" - port = 0 - dev = False - target_vm = "" - - -class Req: - def __init__(self) -> None: - self.method = "" - self.path_query = "" - self.body = "" - self.headers: Dict[str, str] = {} - - -class Response: - def __init__(self, status: int) -> None: - self.status = status - self.body = "" - self.headers: Dict[str, str] = {} - self.version = version.version - - -class Proxy: - def __init__(self, conf_path: str, req: Req = Req(), timeout: float = 10.0) -> None: - self.read_conf(conf_path) - - self.req = req - self.res: Optional[Response] = None - self.timeout = float(timeout) - - self._prepared_request: Optional[requests.PreparedRequest] = None - - def on_done(self) -> None: - print(json.dumps(self.res.__dict__)) - - @staticmethod - def valid_path(path: str) -> bool: - """Check does not contain a hostname in the path""" - return urlparse(path).hostname is None - - def err_on_done(self): - print(json.dumps(self.res.__dict__)) - sys.exit(1) - - def read_conf(self, conf_path: str) -> None: - if not os.path.isfile(conf_path): - self.simple_error(500, "Configuration file does not exist at {}".format(conf_path)) - self.err_on_done() - - try: - with open(conf_path) as fh: - conf_in = yaml.safe_load(fh) - except yaml.YAMLError: - self.simple_error( - 500, - "YAML syntax error while reading configuration file {}".format(conf_path), - ) - self.err_on_done() - except Exception: - self.simple_error( - 500, - "Error while opening or reading configuration file {}".format(conf_path), - ) - self.err_on_done() - - req_conf_keys = set(("host", "scheme", "port")) - missing_keys = req_conf_keys - set(conf_in.keys()) - if len(missing_keys) > 0: - self.simple_error( - 500, "Configuration file missing required keys: {}".format(missing_keys) - ) - self.err_on_done() - - self.conf = Conf() - self.conf.host = conf_in["host"] - self.conf.scheme = conf_in["scheme"] - self.conf.port = conf_in["port"] - - if "dev" in conf_in and conf_in["dev"]: - self.conf.dev = True - else: - if "target_vm" not in conf_in: - self.simple_error( - 500, - ( - "Configuration file missing `target_vm` key, which is required " - "when not in development mode" - ), - ) - self.err_on_done() - - self.conf.target_vm = conf_in["target_vm"] - - # callback for handling non-JSON content. in production-like - # environments, we want to call `qvm-move-to-vm` (and expressly not - # `qvm-move`, since we want to include the destination VM name) to - # move the content to the target VM. for development and testing, we - # keep the file on the local VM. - # - # In any case, this callback mutates the given result object (in - # `res`) to include the name of the new file, or to indicate errors. - def on_save(self, fh: IO[bytes], res: Response) -> None: - fn = str(uuid.uuid4()) - - try: - with tempfile.TemporaryDirectory() as tmpdir: - tmpfile = os.path.join(os.path.abspath(tmpdir), fn) - subprocess.run(["cp", fh.name, tmpfile]) - if self.conf.dev is not True: - subprocess.run(["qvm-move-to-vm", self.conf.target_vm, tmpfile]) - except Exception: - res.status = 500 - res.headers["Content-Type"] = "application/json" - res.headers["X-Origin-Content-Type"] = res.headers["Content-Type"] - res.body = json.dumps( - {"error": "Unhandled error while handling non-JSON content, sorry"} - ) - return - - res.headers["Content-Type"] = "application/json" - res.headers["X-Origin-Content-Type"] = res.headers["Content-Type"] - res.body = json.dumps({"filename": fn}) - - def simple_error(self, status: int, err: str) -> None: - res = Response(status) - res.body = json.dumps({"error": err}) - res.headers = {"Content-Type": "application/json"} - - self.res = res - - def normalize_path(self, parsed: ParseResult) -> ParseResult: - """ - This is copied from the furl library - SPDX-License-Identifier: Unlicense - - Example: '//a/./b/../c//' -> '/a/c/' - """ - path = parsed.path - is_dir = path[-1] == "/" - path = posixpath.normpath(path) - if is_dir: - # Re-add the trailing / - path += "/" - if path.startswith("//"): - # https://bugs.python.org/issue636648 - path = "/" + path.lstrip("/") - - return parsed._replace(path=path) - - def prep_request(self) -> None: - scheme = self.conf.scheme - host = self.conf.host - port = self.conf.port - - path = self.req.path_query - method = self.req.method - - if not self.valid_path(path): - self.simple_error(400, "Path provided in request did not look valid") - raise ValueError("Path provided was invalid") - - parsed = urlparse("{}://{}:{}/{}".format(scheme, host, port, path)) - parsed = self.normalize_path(parsed) - - # urlparse only errors on an invalid port if you examine it - # manually. - try: - _ = parsed.port - except ValueError as err: - logger.error(err) - self.simple_error(500, "Proxy error while generating URL to request") - raise ValueError("Error generating URL from provided values") - - preq = requests.Request(method, parsed.geturl()) - preq.headers = self.req.headers - preq.data = self.req.body - prep = preq.prepare() - - self._prepared_request = prep - - def handle_json_response(self) -> None: - res = Response(self._presp.status_code) - - res.headers = dict(self._presp.headers) - res.body = self._presp.content.decode() - - self.res = res - - def handle_non_json_response(self) -> None: - res = Response(self._presp.status_code) - - # Create a NamedTemporaryFile, we don't want - # to delete it after closing. - fh = tempfile.NamedTemporaryFile(delete=False) - - for c in self._presp.iter_content(10): - fh.write(c) - - fh.close() - - res.headers = dict(self._presp.headers) - - self.on_save(fh, res) - - self.res = res - - def handle_response(self) -> None: - logger.debug("Handling response") - - if is_json_content_type(self._presp.headers["content-type"]): - self.handle_json_response() - else: - self.handle_non_json_response() - - # https://mypy.readthedocs.io/en/latest/kinds_of_types.html#union-types - # To make sure that mypy knows the type of self.res is not None. - assert self.res - # headers is a Requests class which doesn't JSON serialize. - # coerce it into a normal dict so it will - self.res.headers = dict(self.res.headers) - - def proxy(self) -> None: - try: - self.prep_request() - # To confirm that we have a prepared request before the proxy call - assert self._prepared_request - logger.debug("Sending request") - s = requests.Session() - self._presp = s.send(self._prepared_request, timeout=self.timeout) - self._presp.raise_for_status() - self.handle_response() - except ValueError as e: - logger.error(e) - - # effectively a 4xx error - # we have set self.response to indicate an error - pass - except requests.exceptions.Timeout as e: - # Timeout covers both ConnectTimeout and ReadTimeout - logger.error(e) - self.simple_error(http.HTTPStatus.GATEWAY_TIMEOUT, "request timed out") - except ( - requests.exceptions.ConnectionError, # covers ProxyError, SSLError - requests.exceptions.TooManyRedirects, - ) as e: - logger.error(e) - self.simple_error(http.HTTPStatus.BAD_GATEWAY, "could not connect to server") - except requests.exceptions.HTTPError as e: - logger.error(e) - try: - self.simple_error( - e.response.status_code, - http.HTTPStatus(e.response.status_code).phrase.lower(), - ) - except ValueError: - # Return a generic error message when the response - # status code is not found in http.HTTPStatus. - self.simple_error(e.response.status_code, "unspecified server error") - except Exception as e: - logger.error(e) - self.simple_error(http.HTTPStatus.INTERNAL_SERVER_ERROR, "internal proxy error") - self.on_done() diff --git a/proxy/securedrop_proxy/version.py b/proxy/securedrop_proxy/version.py deleted file mode 100644 index 57fde319e..000000000 --- a/proxy/securedrop_proxy/version.py +++ /dev/null @@ -1 +0,0 @@ -version = "0.4.1\n" diff --git a/proxy/setup.cfg b/proxy/setup.cfg deleted file mode 100644 index 997bc30e0..000000000 --- a/proxy/setup.cfg +++ /dev/null @@ -1,9 +0,0 @@ -[flake8] -exclude = - .git, - __pycache__, - -max-line-length = 100 - -builtins = - _, diff --git a/proxy/setup.py b/proxy/setup.py deleted file mode 100644 index 1bbabd8fb..000000000 --- a/proxy/setup.py +++ /dev/null @@ -1,30 +0,0 @@ -import pkgutil - -import setuptools - -with open("README.md", "r") as fh: - long_description = fh.read() - -setuptools.setup( - name="securedrop-proxy", - version="0.0.0", - author="Freedom of the Press Foundation", - author_email="securedrop@freedom.press", - description="SecureDrop Qubes proxy service", - long_description=long_description, - long_description_content_type="text/markdown", - license="GPLv3+", - install_requires=["requests", "furl", "pyyaml", "werkzeug"], - python_requires=">=3.7", - url="https://github.com/freedomofpress/securedrop-proxy", - packages=setuptools.find_packages(exclude=["docs", "tests"]), - classifiers=( - "Development Status :: 3 - Alpha", - "Programming Language :: Python :: 3", - "Topic :: Software Development :: Libraries :: Python Modules", - "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", - "Intended Audience :: Developers", - "Operating System :: OS Independent", - ), - entry_points={"console_scripts": ["sd-proxy = securedrop_proxy.entrypoint:start"]}, -) diff --git a/proxy/src/config_env.rs b/proxy/src/config_env.rs new file mode 100644 index 000000000..b24ac26d5 --- /dev/null +++ b/proxy/src/config_env.rs @@ -0,0 +1,6 @@ +use anyhow::Result; +use std::env; + +pub fn read(name: &str) -> Result { + Ok(env::var(name)?) +} diff --git a/proxy/src/config_qubesdb.rs b/proxy/src/config_qubesdb.rs new file mode 100644 index 000000000..fd7b0c894 --- /dev/null +++ b/proxy/src/config_qubesdb.rs @@ -0,0 +1,32 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + +use anyhow::{bail, Result}; +use std::ffi::{CStr, CString}; +use std::ptr; + +pub fn read(name: &str) -> Result { + let path = format!("/vm-config/{name}"); + + let path_raw = CString::new(path.clone()).unwrap().into_raw(); + let mut len: u32 = 0; + // SAFETY: path_raw will owned by the C caller and MUST be retaken. When + // len == 0, value_unsafe = NUL and MUST NOT be passed to CStr::from_ptr(). + let value_raw = unsafe { + let db = qdb_open(ptr::null_mut()); + let value_unsafe = qdb_read(db, path_raw, &mut len); + qdb_close(db); + let _ = CString::from_raw(path_raw); // retake + + if len > 0 { + CStr::from_ptr(value_unsafe) + } else { + bail!("Could not read from QubesDB: {}", path); + } + }; + + let value = value_raw.to_owned().into_string()?; + Ok(value) +} diff --git a/proxy/src/main.rs b/proxy/src/main.rs index 148d5204f..1bfc07183 100644 --- a/proxy/src/main.rs +++ b/proxy/src/main.rs @@ -1,5 +1,179 @@ #![deny(clippy::all)] -fn main() { - println!("Hello, world!"); +use anyhow::{bail, Result}; +use futures_util::StreamExt; +use reqwest::header::HeaderMap; +use reqwest::Method; +use reqwest::{Client, Response}; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::io; +use std::io::Write; +use std::process::ExitCode; +use std::str::FromStr; +use std::time::Duration; +use url::Url; + +#[cfg(feature = "qubesdb")] +mod config_qubesdb; +#[cfg(feature = "qubesdb")] +use config_qubesdb as config; + +#[cfg(not(feature = "qubesdb"))] +mod config_env; +#[cfg(not(feature = "qubesdb"))] +use config_env as config; + +const ENV_CONFIG: &str = "SD_PROXY_ORIGIN"; + +/// Incoming requests (as JSON) received over stdin +#[derive(Deserialize, Debug)] +#[serde(deny_unknown_fields)] +struct IncomingRequest { + method: String, + path_query: String, + stream: bool, + #[serde(default)] + headers: HashMap, + body: Option, + #[serde(default = "default_timeout")] + timeout: u64, +} + +/// Default timeout for requests; serde requires this be a function +fn default_timeout() -> u64 { + 10 +} + +/// Serialization format for non-streamed requests +#[derive(Serialize, Debug)] +struct OutgoingResponse { + status: u16, + headers: HashMap, + body: String, +} + +/// In a streamed response, we emit the checksum after the streaming finishes +#[derive(Serialize, Debug)] +struct StreamMetadataResponse { + headers: HashMap, +} + +/// Serialization format for errors, always over stderr +#[derive(Serialize, Debug)] +struct ErrorResponse { + error: String, +} + +fn headers_to_map(resp: &Response) -> Result> { + let mut headers = HashMap::new(); + for (name, value) in resp.headers() { + headers.insert(name.to_string(), value.to_str()?.to_string()); + } + Ok(headers) +} + +async fn handle_json_response(resp: Response) -> Result<()> { + let headers = headers_to_map(&resp)?; + let outgoing_response = OutgoingResponse { + status: resp.status().as_u16(), + headers, + body: resp.text().await?, + }; + println!("{}", serde_json::to_string(&outgoing_response)?); + Ok(()) +} + +async fn handle_stream_response(resp: Response) -> Result<()> { + // Get the headers, will be output later but we want to fail early if it's missing/invalid + let headers = headers_to_map(&resp)?; + let mut stdout = io::stdout().lock(); + let mut stream = resp.bytes_stream(); + // Stream the response, printing bytes as we receive them + while let Some(item) = stream.next().await { + stdout.write_all(&item?)?; + // TODO: can we flush at smarter intervals? + stdout.flush()?; + } + // Emit the headers as stderr + eprintln!( + "{}", + serde_json::to_string(&StreamMetadataResponse { headers })? + ); + Ok(()) +} + +async fn proxy() -> Result<()> { + // Get the hostname from the environment or QubesDB + let origin = config::read(ENV_CONFIG)?; + // Read incoming request from stdin (must be on single line) + let mut buffer = String::new(); + io::stdin().read_line(&mut buffer)?; + let incoming_request: IncomingRequest = serde_json::from_str(&buffer)?; + // We construct the URL by first parsing the origin and then appending the + // path query. This forces the path query to be part of the path and prevents + // it from getting itself into the hostname. + let origin = Url::parse(&origin)?; + // TODO: Consider just allowlisting a number of API paths instead of relying + // on the url library to join it properly and avoid type confusion + let url = origin.join(&incoming_request.path_query)?; + // n.b. unclear how useful this check is, if Url::parse() is compromised, + // then why do we trust url.origin()? + // In any case, we know mixing URL parsers can be a security risk, + // (c.f. https://daniel.haxx.se/blog/2022/01/10/dont-mix-url-parsers/) + // and certainly there's no harm in the additional check. + if url.origin() != origin.origin() { + bail! {"request would escape configured origin"} + } + + let client = Client::new(); + let mut req = + client.request(Method::from_str(&incoming_request.method)?, url); + let header_map = HeaderMap::try_from(&incoming_request.headers)?; + req = req + .headers(header_map) + .timeout(Duration::from_secs(incoming_request.timeout)); + if let Some(body) = incoming_request.body { + req = req.body(body); + } + // Fire off the request! + let resp = req.send().await?; + // We return the output in two ways, either a JSON blob or stream the output. + // JSON is used for HTTP 4xx, 5xx, and all non-stream requests. + if !incoming_request.stream + || resp.status().is_client_error() + || resp.status().is_server_error() + { + handle_json_response(resp).await?; + } else { + handle_stream_response(resp).await?; + } + Ok(()) +} + +#[tokio::main(flavor = "current_thread")] +async fn main() -> ExitCode { + match proxy().await { + Ok(()) => ExitCode::SUCCESS, + Err(err) => { + // Try to serialize into our error format + let resp = ErrorResponse { + error: err.to_string(), + }; + match serde_json::to_string(&resp) { + Ok(json) => { + // Print the error to stderr + eprintln!("{json}") + } + Err(_) => { + // It should be near impossible that an error message + // is not JSON serializable, but just handle this corner + // case explicitly + // TODO: attempt to log underlying error + eprintln!(r#"{{"error": "unable to serialize error"}}"#) + } + }; + ExitCode::FAILURE + } + } } diff --git a/proxy/tests/conftest.py b/proxy/tests/conftest.py new file mode 100644 index 000000000..95376bfbd --- /dev/null +++ b/proxy/tests/conftest.py @@ -0,0 +1,32 @@ +import json +import os +import subprocess +from typing import Optional, Union + +import pytest + + +@pytest.fixture(scope="session") +def proxy_bin() -> str: + if "PROXY_BIN" in os.environ: + # allow running tests against e.g. a packaged binary + return os.environ["PROXY_BIN"] + # default debug path, expects `cargo build` to already have been run + metadata = subprocess.check_output(["cargo", "metadata"]) + return json.loads(metadata)["target_directory"] + "/debug/securedrop-proxy" + + +@pytest.fixture +def proxy_request(httpbin, proxy_bin): + def proxy_( + input: Union[bytes, dict], origin: Optional[str] = None + ) -> subprocess.CompletedProcess: + if isinstance(input, dict): + input = json.dumps(input).encode() + if origin is None: + origin = httpbin.url + return subprocess.run( + [proxy_bin], env={"SD_PROXY_ORIGIN": origin}, input=input, capture_output=True + ) + + return proxy_ diff --git a/proxy/tests/files/badgateway-config.yaml b/proxy/tests/files/badgateway-config.yaml deleted file mode 100644 index 89396443c..000000000 --- a/proxy/tests/files/badgateway-config.yaml +++ /dev/null @@ -1,5 +0,0 @@ -host: sdproxytest.local -scheme: https -port: 8000 -target_vm: compost -dev: False diff --git a/proxy/tests/files/dev-config.yaml b/proxy/tests/files/dev-config.yaml deleted file mode 100644 index 8e72283a2..000000000 --- a/proxy/tests/files/dev-config.yaml +++ /dev/null @@ -1,5 +0,0 @@ -host: jsonplaceholder.typicode.com -scheme: https -port: 443 -target_vm: compost -dev: True diff --git a/proxy/tests/files/invalid-config.yaml b/proxy/tests/files/invalid-config.yaml deleted file mode 100644 index 29d7af94c..000000000 --- a/proxy/tests/files/invalid-config.yaml +++ /dev/null @@ -1,5 +0,0 @@ -host: badport.local:-1 -scheme: https -port: 443 -target_vm: compost -dev: False diff --git a/proxy/tests/files/invalid_yaml.yaml b/proxy/tests/files/invalid_yaml.yaml deleted file mode 100644 index fad3d369d..000000000 --- a/proxy/tests/files/invalid_yaml.yaml +++ /dev/null @@ -1 +0,0 @@ -[:thisisbad diff --git a/proxy/tests/files/local-config.yaml b/proxy/tests/files/local-config.yaml deleted file mode 100644 index 7bd20fc78..000000000 --- a/proxy/tests/files/local-config.yaml +++ /dev/null @@ -1,5 +0,0 @@ -host: localhost -scheme: http -port: 8000 -target_vm: compost -dev: False diff --git a/proxy/tests/files/missing-key.yaml b/proxy/tests/files/missing-key.yaml deleted file mode 100644 index 8e429958d..000000000 --- a/proxy/tests/files/missing-key.yaml +++ /dev/null @@ -1,4 +0,0 @@ -host: jsonplaceholder.typicode.com -scheme: https -target_vm: compost -dev: False diff --git a/proxy/tests/files/missing-target-vm.yaml b/proxy/tests/files/missing-target-vm.yaml deleted file mode 100644 index 2ea9cc53a..000000000 --- a/proxy/tests/files/missing-target-vm.yaml +++ /dev/null @@ -1,4 +0,0 @@ -host: jsonplaceholder.typicode.com -scheme: https -port: 443 -dev: False diff --git a/proxy/tests/files/valid-config.yaml b/proxy/tests/files/valid-config.yaml deleted file mode 100644 index 282052a86..000000000 --- a/proxy/tests/files/valid-config.yaml +++ /dev/null @@ -1,5 +0,0 @@ -host: jsonplaceholder.typicode.com -scheme: https -port: 443 -target_vm: compost -dev: False diff --git a/proxy/tests/test_entrypoint.py b/proxy/tests/test_entrypoint.py deleted file mode 100644 index 488bce67d..000000000 --- a/proxy/tests/test_entrypoint.py +++ /dev/null @@ -1,151 +0,0 @@ -import contextlib -import http -import io -import json -import os -import platform -import tempfile -import unittest -from unittest.mock import patch - -import vcr - -from securedrop_proxy import entrypoint - - -@contextlib.contextmanager -def sdhome(*args, **kwds): - with tempfile.TemporaryDirectory() as tmphome: - os.environ["SECUREDROP_HOME"] = tmphome - try: - yield tmphome - finally: - del os.environ["SECUREDROP_HOME"] - - -class TestEntrypoint(unittest.TestCase): - """ - Test the entrypoint used in production. - """ - - def test_missing_config(self): - config_path = "/tmp/nonexistent-config.yaml" - self.assertFalse(os.path.exists(config_path)) - - output = None - with ( - patch( - "sys.argv", new_callable=lambda: ["sd-proxy", config_path] - ) as mock_argv, # noqa: F841 - patch("sys.stdout", new_callable=io.StringIO) as mock_stdout, - ): - with self.assertRaises(SystemExit), sdhome(): - entrypoint.start() - output = mock_stdout.getvalue() - - response = json.loads(output) - self.assertEqual(response["status"], http.HTTPStatus.INTERNAL_SERVER_ERROR) - body = json.loads(response["body"]) - self.assertEqual( - body["error"], "Configuration file does not exist at {}".format(config_path) - ) - - @patch("securedrop_proxy.entrypoint.logging") - @patch("securedrop_proxy.entrypoint.SysLogHandler") - @patch("securedrop_proxy.entrypoint.TimedRotatingFileHandler") - def test_configure_logging(self, mock_log_conf, mock_log_conf_sys, mock_logging): - with sdhome() as homedir: - mock_log_file = os.path.join(homedir, "logs", "proxy.log") - entrypoint.configure_logging() - mock_log_conf.assert_called_once_with(mock_log_file) - # For rsyslog handler - if platform.system() != "Linux": # pragma: no cover - syslog_file = "/var/run/syslog" - else: - syslog_file = "/dev/log" - mock_log_conf_sys.assert_called_once_with(address=syslog_file) - mock_logging.getLogger.assert_called_once_with() - - def test_unwritable_log_folder(self): - """ - Tests a permission problem in `configure_logging`. - """ - with sdhome(): - with patch( - "os.makedirs", side_effect=PermissionError("[Errno 13] Permission denied: '/foo'") - ): - with patch("sys.stdout", new_callable=io.StringIO) as mock_stdout: - with self.assertRaises(SystemExit): - entrypoint.start() - output = mock_stdout.getvalue() - - response = json.loads(output) - self.assertEqual(response["status"], http.HTTPStatus.INTERNAL_SERVER_ERROR) - body = json.loads(response["body"]) - self.assertIn("Permission denied: ", body["error"]) - - def test_wrong_number_of_arguments(self): - with sdhome() as home: # noqa: F841 - with ( - patch("sys.argv", new_callable=lambda: ["sd-proxy"]) as mock_argv, # noqa: F841 - patch("sys.stdout", new_callable=io.StringIO) as mock_stdout, - ): - with self.assertRaises(SystemExit): - entrypoint.start() - output = mock_stdout.getvalue() - - response = json.loads(output) - self.assertEqual(response["status"], http.HTTPStatus.INTERNAL_SERVER_ERROR) - body = json.loads(response["body"]) - self.assertEqual( - body["error"], "sd-proxy script not called with path to configuration file" - ) - - def test_empty_input(self): - config_path = "tests/files/valid-config.yaml" - self.assertTrue(os.path.exists(config_path)) - - with sdhome() as home: # noqa: F841 - with ( - patch( - "sys.stdin", new_callable=lambda: io.StringIO("") - ) as mock_stdin, # noqa: F841 - patch("sys.stdout", new_callable=io.StringIO) as mock_stdout, - patch( - "sys.argv", new_callable=lambda: ["sd-proxy", config_path] - ) as mock_argv, # noqa: F841 - ): - entrypoint.start() - output = mock_stdout.getvalue() - - response = json.loads(output) - self.assertEqual(response["status"], http.HTTPStatus.BAD_REQUEST) - body = json.loads(response["body"]) - self.assertEqual(body["error"], "Invalid JSON in request") - - @vcr.use_cassette("fixtures/main_json_response.yaml") - def test_json_response(self): - config_path = "tests/files/valid-config.yaml" - self.assertTrue(os.path.exists(config_path)) - - test_input = { - "method": "GET", - "path_query": "/posts?userId=1", - } - - output = None - with ( - sdhome() as home, # noqa: F841 - patch( - "sys.stdin", new_callable=lambda: io.StringIO(json.dumps(test_input)) - ) as mock_stding, # noqa: F841 - patch("sys.stdout", new_callable=io.StringIO) as mock_stdout, - patch( - "sys.argv", new_callable=lambda: ["sd-proxy", config_path] - ) as mock_argv, # noqa: F841 - ): - entrypoint.start() - output = mock_stdout.getvalue() - - response = json.loads(output) - self.assertEqual(response["status"], http.HTTPStatus.OK) diff --git a/proxy/tests/test_errors.py b/proxy/tests/test_errors.py new file mode 100644 index 000000000..f848d08b9 --- /dev/null +++ b/proxy/tests/test_errors.py @@ -0,0 +1,70 @@ +import os +import subprocess + + +def test_missing_config(proxy_bin): + env = os.environ.copy() + if "SD_PROXY_ORIGIN" in env: + del env["SD_PROXY_ORIGIN"] + result = subprocess.run([proxy_bin], env=env, capture_output=True) + assert result.returncode == 1 + assert result.stderr.decode().strip() == '{"error":"environment variable not found"}' + + +def test_empty_input(proxy_request): + result = proxy_request(input=b"") + assert result.returncode == 1 + assert ( + result.stderr.decode().strip() == '{"error":"EOF while parsing a value at line 1 column 0"}' + ) + + +def test_input_invalid(proxy_request): + test_input = b'"foo": "bar", "baz": "bliff"}' + result = proxy_request(input=test_input) + assert result.returncode == 1 + assert ( + result.stderr.decode().strip() + == '{"error":"invalid type: string \\"foo\\", ' + + 'expected struct IncomingRequest at line 1 column 5"}' + ) + + +def test_input_missing_keys(proxy_request): + test_input = b'{"foo": "bar", "baz": "bliff"}' + result = proxy_request(input=test_input) + assert result.returncode == 1 + assert ( + result.stderr.decode().strip() + == '{"error":"unknown field `foo`, expected one of `method`, ' + + '`path_query`, `stream`, `headers`, `body`, `timeout` at line 1 column 6"}' + ) + + +def test_invalid_origin(proxy_request): + test_input = { + "method": "GET", + "path_query": "/status/200", + "stream": False, + } + # invalid port + result = proxy_request(input=test_input, origin="http://127.0.0.1:-1/foo") + assert result.returncode == 1 + assert result.stderr.decode().strip() == '{"error":"invalid port number"}' + + +def test_cannot_connect(proxy_request): + test_input = { + "method": "GET", + "path_query": "/", + "stream": False, + } + # .test is a reserved TLD, so it should never resolve + result = proxy_request(input=test_input, origin="http://missing.test/foo") + assert result.returncode == 1 + assert ( + result.stderr.decode().strip() + == '{"error":"error sending request for url (http://missing.test/): ' + + "error trying to connect: dns error: failed to lookup address information: " + + 'Name or service not known"}' + ) diff --git a/proxy/tests/test_json.py b/proxy/tests/test_json.py deleted file mode 100644 index d268e34ac..000000000 --- a/proxy/tests/test_json.py +++ /dev/null @@ -1,21 +0,0 @@ -import unittest - -from securedrop_proxy import json - - -class JsonTest(unittest.TestCase): - def test_dumps(self): - """Simple check since this is a passthrough to stdlib json""" - self.assertEqual( - json.dumps({"foo": "bar", "baz": ["one"]}), '{"foo": "bar", "baz": ["one"]}' - ) - - def test_loads(self): - # Verify basic loading works - self.assertEqual( - json.loads('{"foo": "bar", "baz": ["one"]}'), {"foo": "bar", "baz": ["one"]} - ) - # But duplicate keys are rejected - with self.assertRaises(ValueError) as exc: - json.loads('{"foo": "bar", "foo": "baz"}') - self.assertEqual(str(exc.exception), "Key 'foo' found twice in JSON object") diff --git a/proxy/tests/test_main.py b/proxy/tests/test_main.py deleted file mode 100644 index 66289660c..000000000 --- a/proxy/tests/test_main.py +++ /dev/null @@ -1,230 +0,0 @@ -import http -import json -import subprocess -import sys -import types -import unittest -import uuid -from io import StringIO - -import vcr - -from securedrop_proxy import main, proxy - - -class TestMain(unittest.TestCase): - def setUp(self): - self.conf_path = "tests/files/valid-config.yaml" - - @vcr.use_cassette("fixtures/main_json_response.yaml") - def test_json_response(self): - test_input_json = """{ "method": "GET", - "path_query": "/posts?userId=1" }""" - - req = proxy.Req() - req.method = "GET" - req.path_query = "" - req.headers = {"Accept": "application/json"} - - # Use custom callbacks - def on_save(self, fh, res): - pass - - def on_done(self): - assert self.res.status == http.HTTPStatus.OK - print(json.dumps(self.res.__dict__)) - - self.p = proxy.Proxy(self.conf_path, req) - - # Patching on_save and on_done - - self.p.on_done = types.MethodType(on_done, self.p) - self.p.on_save = types.MethodType(on_save, self.p) - - saved_stdout = sys.stdout - try: - out = StringIO() - sys.stdout = out - main.__main__(test_input_json, self.p) - output = out.getvalue().strip() - finally: - sys.stdout = saved_stdout - - response = json.loads(output) - for item in json.loads(response["body"]): - self.assertEqual(item["userId"], 1) - - @vcr.use_cassette("fixtures/main_json_response_with_timeout.yaml") - def test_json_response_with_timeout(self): - test_input_json = """{ "method": "GET", - "path_query": "/posts?userId=1", - "timeout": 40.0 }""" - - req = proxy.Req() - req.method = "GET" - req.path_query = "" - req.headers = {"Accept": "application/json"} - - # Use custom callbacks - def on_save(self, fh, res): - pass - - def on_done(self): - assert self.res.status == http.HTTPStatus.OK - print(json.dumps(self.res.__dict__)) - - self.p = proxy.Proxy(self.conf_path, req) - - # Patching on_save and on_done - - self.p.on_done = types.MethodType(on_done, self.p) - self.p.on_save = types.MethodType(on_save, self.p) - - saved_stdout = sys.stdout - try: - out = StringIO() - sys.stdout = out - main.__main__(test_input_json, self.p) - output = out.getvalue().strip() - finally: - sys.stdout = saved_stdout - - # Test that the right timeout was set in proxy object - assert self.p.timeout == 40.0 - - response = json.loads(output) - for item in json.loads(response["body"]): - self.assertEqual(item["userId"], 1) - - @vcr.use_cassette("fixtures/main_non_json_response.yaml") - def test_non_json_response(self): - test_input_json = """{ "method": "GET", - "path_query": "" }""" - - def on_save(self, fh, res): - subprocess.run(["cp", fh.name, "/tmp/{}".format(self.fn)]) - - res.headers["X-Origin-Content-Type"] = res.headers["Content-Type"] - res.headers["Content-Type"] = "application/json" - res.body = json.dumps({"filename": self.fn}) - - self.p = proxy.Proxy(self.conf_path, proxy.Req()) - - # Patching on_save to tests - self.p.on_save = types.MethodType(on_save, self.p) - self.p.fn = str(uuid.uuid4()) - - saved_stdout = sys.stdout - try: - out = StringIO() - sys.stdout = out - main.__main__(test_input_json, self.p) - output = out.getvalue().strip() - finally: - sys.stdout = saved_stdout - - response = json.loads(output) - self.assertEqual(response["status"], 200) - - # The proxy should have created a filename in the response body - self.assertIn("filename", response["body"]) - - # The file should not be empty - with open("/tmp/{}".format(self.p.fn)) as f: - saved_file = f.read() - - # We expect HTML content in the file from the test data - self.assertIn("", saved_file) - - def test_input_invalid_json(self): - test_input_json = """"foo": "bar", "baz": "bliff" }""" - - def on_save(self, fh, res): - pass - - def on_done(self): - res = self.res.__dict__ - assert res["status"] == 400 - sys.exit(1) - - p = proxy.Proxy(self.conf_path, proxy.Req()) - - # patching on_save and on_done for tests - - p.on_done = types.MethodType(on_done, p) - p.on_save = types.MethodType(on_save, p) - - with self.assertRaises(SystemExit): - main.__main__(test_input_json, p) - - def test_input_missing_keys(self): - test_input_json = """{ "foo": "bar", "baz": "bliff" }""" - - def on_save(self, fh, res): - pass - - def on_done(self): - res = self.res.__dict__ - assert res["status"] == 400 - assert res["body"] == '{"error": "Missing keys in request"}', res - sys.exit(1) - - p = proxy.Proxy(self.conf_path, proxy.Req()) - - # patching on_save and on_done for tests - - p.on_done = types.MethodType(on_done, p) - p.on_save = types.MethodType(on_save, p) - - with self.assertRaises(SystemExit): - main.__main__(test_input_json, p) - - @vcr.use_cassette("fixtures/main_input_headers.yaml") - def test_input_headers(self): - test_input = { - "method": "GET", - "path_query": "/posts?userId=1", - "headers": {"X-Test-Header": "th"}, - } - - def on_save(self, fh, res): - pass - - p = proxy.Proxy(self.conf_path, proxy.Req()) - main.__main__(json.dumps(test_input), p) - self.assertEqual(p.req.headers, test_input["headers"]) - - @vcr.use_cassette("fixtures/main_input_body.yaml") - def test_input_body(self): - test_input = { - "method": "POST", - "path_query": "/posts", - "body": {"id": 42, "title": "test"}, - } - - def on_save(self, fh, res): - pass - - p = proxy.Proxy(self.conf_path, proxy.Req()) - - # Patching on_save for tests - - p.on_save = types.MethodType(on_save, p) - - main.__main__(json.dumps(test_input), p) - self.assertEqual(p.req.body, test_input["body"]) - - @vcr.use_cassette("fixtures/main_non_json_response.yaml") - def test_default_callbacks(self): - test_input = { - "method": "GET", - "path_query": "", - } - - p = proxy.Proxy(self.conf_path, proxy.Req()) - p.on_done = unittest.mock.MagicMock() - p.on_save = unittest.mock.MagicMock() - - main.__main__(json.dumps(test_input), p) - self.assertEqual(p.on_save.call_count, 1) - self.assertEqual(p.on_done.call_count, 1) diff --git a/proxy/tests/test_proxy.py b/proxy/tests/test_proxy.py index 5d6a10f24..8a7286e75 100644 --- a/proxy/tests/test_proxy.py +++ b/proxy/tests/test_proxy.py @@ -1,481 +1,118 @@ -import http import json -import sys -import tempfile -import types -import unittest -import uuid -from io import StringIO -from unittest.mock import patch - -import requests -import vcr - -from securedrop_proxy import proxy, version - - -class TestProxyValidConfig(unittest.TestCase): - def setUp(self): - self.conf_path = "tests/files/valid-config.yaml" - - def on_save(self, fh, res): - res.headers["X-Origin-Content-Type"] = res.headers["Content-Type"] - res.headers["Content-Type"] = "application/json" - res.body = json.dumps({"filename": self.fn}) - - def on_done(self, res): - res.headers["X-Origin-Content-Type"] = res.headers["Content-Type"] - res.headers["Content-Type"] = "application/json" - - def test_version(self): - req = proxy.Req() - req.method = "GET" - req.path_query = "" - req.headers = {"Accept": "application/json"} - - p = proxy.Proxy(self.conf_path) - p.proxy() - - self.assertEqual(p.res.version, version.version) - - @vcr.use_cassette("fixtures/basic_proxy_functionality.yaml") - def test_proxy_basic_functionality(self): - req = proxy.Req() - req.method = "GET" - req.path_query = "" - req.headers = {"Accept": "application/json"} - - def on_save(self, fh, res): - res.headers["X-Origin-Content-Type"] = res.headers["Content-Type"] - res.headers["Content-Type"] = "application/json" - res.body = json.dumps({"filename": self.fn}) - - p = proxy.Proxy(self.conf_path, req) - # Patching on_save for test - p.on_save = types.MethodType(on_save, p) - p.fn = str(uuid.uuid4()) - p.proxy() - - self.assertEqual(p.res.status, 200) - self.assertEqual(p.res.body, json.dumps({"filename": p.fn})) - self.assertEqual(p.res.headers["Content-Type"], "application/json") - - @vcr.use_cassette("fixtures/proxy_404.yaml") - def test_proxy_produces_404(self): - req = proxy.Req() - req.method = "GET" - req.path_query = "/notfound" - req.headers = {"Accept": "application/json"} - - p = proxy.Proxy(self.conf_path, req) - - p.proxy() - - self.assertEqual(p.res.status, 404) - self.assertEqual(p.res.headers["Content-Type"], "application/json") - - @vcr.use_cassette("fixtures/proxy_parameters.yaml") - def test_proxy_handles_query_params_gracefully(self): - req = proxy.Req() - req.method = "GET" - req.path_query = "/posts?userId=1" - req.headers = {"Accept": "application/json"} - - p = proxy.Proxy(self.conf_path, req) - - p.proxy() - - self.assertEqual(p.res.status, 200) - self.assertIn("application/json", p.res.headers["Content-Type"]) - body = json.loads(p.res.body) - for item in body: - self.assertEqual(item["userId"], 1) - - # No cassette needed as no network request should be sent - def test_proxy_400_bad_path(self): - req = proxy.Req() - req.method = "GET" - req.path_query = "http://badpath.lol/path" - req.headers = {"Accept": "application/json"} - - p = proxy.Proxy(self.conf_path, req) - - p.proxy() - - self.assertEqual(p.res.status, 400) - self.assertEqual(p.res.headers["Content-Type"], "application/json") - self.assertIn("Path provided in request did not look valid", p.res.body) - - @vcr.use_cassette("fixtures/proxy_200_valid_path.yaml") - def test_proxy_200_valid_path(self): - req = proxy.Req() - req.method = "GET" - req.path_query = "/posts/1" - req.headers = {"Accept": "application/json"} - - p = proxy.Proxy(self.conf_path, req) - - p.proxy() - - self.assertEqual(p.res.status, 200) - self.assertIn("application/json", p.res.headers["Content-Type"]) - body = json.loads(p.res.body) - self.assertEqual(body["userId"], 1) - - -class TestProxyInvalidConfig(unittest.TestCase): - def setUp(self): - self.conf_path = "tests/files/invalid-config.yaml" - - def on_save(self, fh, res): - self.fn = str(uuid.uuid4()) - res.headers["X-Origin-Content-Type"] = res.headers["Content-Type"] - res.headers["Content-Type"] = "application/json" - res.body = json.dumps({"filename": self.fn}) - - # No cassette needed as no network request should be sent - def test_proxy_500_misconfiguration(self): - req = proxy.Req() - req.method = "GET" - req.path_query = "/posts/1" - req.headers = {"Accept": "application/json"} - - p = proxy.Proxy(self.conf_path, req) - - p.proxy() - - self.assertEqual(p.res.status, 500) - self.assertEqual(p.res.headers["Content-Type"], "application/json") - self.assertIn("Proxy error while generating URL to request", p.res.body) - - -class TestServerErrorHandling(unittest.TestCase): - def setUp(self): - self.conf_path = "tests/files/local-config.yaml" - - def make_request(self, method="GET", path_query="/", headers=None): - req = proxy.Req() - req.method = method if method else "GET" - req.path_query = path_query if path_query else "/" - req.headers = headers if headers else {"Accept": "application/json"} - return req - - def test_cannot_connect(self): - """ - Test for "502 Bad Gateway" when the server can't be reached. - """ - req = self.make_request() - - p = proxy.Proxy("tests/files/badgateway-config.yaml", req) - p.proxy() - - self.assertEqual(p.res.status, http.HTTPStatus.BAD_GATEWAY) - self.assertIn("application/json", p.res.headers["Content-Type"]) - body = json.loads(p.res.body) - self.assertEqual(body["error"], "could not connect to server") - - def test_server_timeout(self): - """ - Test for "504 Gateway Timeout" when the server times out. - """ - - class TimeoutProxy(proxy.Proxy): - """ - Mocks a slow upstream server. - - VCR cassettes cannot represent a request that takes too - long. This Proxy subclass raises the exception that would - cause. - """ - - def prep_request(self): - raise requests.exceptions.Timeout("test timeout") - - req = self.make_request(path_query="/tarpit") - p = TimeoutProxy(self.conf_path, req, timeout=0.00001) - p.proxy() - - self.assertEqual(p.res.status, http.HTTPStatus.GATEWAY_TIMEOUT) - self.assertIn("application/json", p.res.headers["Content-Type"]) - body = json.loads(p.res.body) - self.assertEqual(body["error"], "request timed out") - - @vcr.use_cassette("fixtures/proxy_bad_request.yaml") - def test_bad_request(self): - """ - Test handling of "400 Bad Request" from the server. - """ - req = self.make_request(path_query="/bad") - p = proxy.Proxy(self.conf_path, req) - p.proxy() - - self.assertEqual(p.res.status, http.HTTPStatus.BAD_REQUEST) - self.assertIn("application/json", p.res.headers["Content-Type"]) - body = json.loads(p.res.body) - self.assertEqual(body["error"], http.HTTPStatus.BAD_REQUEST.phrase.lower()) - - @vcr.use_cassette("fixtures/proxy_unofficial_status.yaml") - def test_unofficial_status(self): - """ - Make sure we handle unofficial status codes from the server. - - Should the server ever need to return a status code not in - Python's http.HTTPStatus, the proxy should still return a - proper JSON error response with a generic error message. - """ - req = self.make_request(path_query="/teapot") - p = proxy.Proxy(self.conf_path, req) - p.proxy() - - self.assertEqual(p.res.status, 499) - self.assertIn("application/json", p.res.headers["Content-Type"]) - body = json.loads(p.res.body) - self.assertEqual(body["error"], "unspecified server error") - - @vcr.use_cassette("fixtures/proxy_internal_server_error.yaml") - def test_internal_server_error(self): - """ - Test handling of "500 Internal Server Error" from the server. - """ - req = self.make_request(path_query="/crash") - p = proxy.Proxy(self.conf_path, req) - p.proxy() - - self.assertEqual(p.res.status, http.HTTPStatus.INTERNAL_SERVER_ERROR) - self.assertIn("application/json", p.res.headers["Content-Type"]) - body = json.loads(p.res.body) - self.assertEqual(body["error"], http.HTTPStatus.INTERNAL_SERVER_ERROR.phrase.lower()) - - @vcr.use_cassette("fixtures/proxy_internal_error.yaml") - def test_internal_error(self): - """ - Ensure that the proxy returns JSON despite internal errors. - """ - - def bad_on_save(self, fh, res, conf): - raise Exception("test internal proxy error") - - req = self.make_request() - p = proxy.Proxy(self.conf_path, req) - - # Patching on_save for tests - p.on_save = types.MethodType(bad_on_save, p) - p.proxy() - - self.assertEqual(p.res.status, http.HTTPStatus.INTERNAL_SERVER_ERROR) - self.assertIn("application/json", p.res.headers["Content-Type"]) - body = json.loads(p.res.body) - self.assertEqual(body["error"], "internal proxy error") - - -class TestProxyMethods(unittest.TestCase): - def setUp(self): - self.res = proxy.Response(status=200) - self.res.body = "babbys request" - - self.conf_path = "tests/files/dev-config.yaml" - - def test_err_on_done(self): - saved_stdout = sys.stdout - try: - out = StringIO() - sys.stdout = out - with self.assertRaises(SystemExit): - p = proxy.Proxy(self.conf_path) - p.res = self.res - p.err_on_done() - output = out.getvalue().strip() - finally: - sys.stdout = saved_stdout - - response = json.loads(output) - self.assertEqual(response["status"], 200) - self.assertEqual(response["body"], "babbys request") - - def test_on_done(self): - saved_stdout = sys.stdout - try: - out = StringIO() - sys.stdout = out - p = proxy.Proxy(self.conf_path) - p.res = self.res - p.on_done() - output = out.getvalue().strip() - finally: - sys.stdout = saved_stdout - - response = json.loads(output) - self.assertEqual(response["status"], 200) - self.assertEqual(response["body"], "babbys request") - - def test_on_save_500_unhandled_error(self): - fh = tempfile.NamedTemporaryFile() - - # Let's generate an error and ensure that an appropriate response - # is sent back to the user - with patch("subprocess.run", side_effect=IOError): - p = proxy.Proxy(self.conf_path) - p.on_save(fh, self.res) - - self.assertEqual(self.res.status, 500) - self.assertEqual(self.res.headers["Content-Type"], "application/json") - self.assertEqual(self.res.headers["X-Origin-Content-Type"], "application/json") - self.assertIn("Unhandled error", self.res.body) - - def test_on_save_200_success(self): - fh = tempfile.NamedTemporaryFile() - - p = proxy.Proxy(self.conf_path) - p.on_save(fh, self.res) - - self.assertEqual(self.res.headers["Content-Type"], "application/json") - self.assertEqual(self.res.headers["X-Origin-Content-Type"], "application/json") - self.assertEqual(self.res.status, 200) - self.assertIn("filename", self.res.body) - - @vcr.use_cassette("fixtures/proxy_callbacks.yaml") - def test_custom_callbacks(self): - """ - Test the handlers in a real proxy request. - """ - conf = proxy.Conf() - conf.host = "jsonplaceholder.typicode.com" - conf.scheme = "https" - conf.port = 443 - - req = proxy.Req() - req.method = "GET" - - on_save_addition = "added by the on_save callback\n" - on_done_addition = "added by the on_done callback\n" - - def on_save(self, fh, res): - res.headers["Content-Type"] = "text/plain" - res.body = on_save_addition - - def on_done(self): - self.res.headers["Content-Type"] = "text/plain" - self.res.body += on_done_addition - - p = proxy.Proxy(self.conf_path, req) - # Patching for tests - p.conf = conf - p.on_done = types.MethodType(on_done, p) - p.on_save = types.MethodType(on_save, p) - p.proxy() - - self.assertEqual(p.res.body, "{}{}".format(on_save_addition, on_done_addition)) - - @vcr.use_cassette("fixtures/proxy_callbacks.yaml") - def test_production_on_save(self): - """ - Test on_save's production file handling. - """ - conf = proxy.Conf() - conf.host = "jsonplaceholder.typicode.com" - conf.scheme = "https" - conf.port = 443 - conf.dev = False - conf.target_vm = "sd-viewer" - - with patch("subprocess.run") as patched_run: - fh = tempfile.NamedTemporaryFile() - p = proxy.Proxy(self.conf_path) - # Patching for tests - p.conf = conf - p.on_save(fh, self.res) - self.assertEqual(patched_run.call_args[0][0][0], "qvm-move-to-vm") - - def test_is_json_content_type(self): - self.assertTrue(proxy.is_json_content_type("application/json")) - self.assertTrue(proxy.is_json_content_type("application/json; charset=utf-8")) - self.assertFalse(proxy.is_json_content_type("application/yaml")) - - -class TestConfig(unittest.TestCase): - def setUp(self): - self.conf_path = "tests/files/dev-config.yaml" - - def test_config_file_does_not_exist(self): - def err_on_done(self): - res = self.res.__dict__ - assert res["status"] == 500 - assert "Configuration file does not exist" in res["body"] - assert res["headers"]["Content-Type"] == "application/json" - sys.exit(1) - - p = proxy.Proxy(self.conf_path) - p.err_on_done = types.MethodType(err_on_done, p) - with self.assertRaises(SystemExit): - p.read_conf("not/a/real/path") - - def test_config_file_when_yaml_is_invalid(self): - def err_on_done(self): - res = self.res.__dict__ - assert res["status"] == 500 - assert "YAML syntax error" in res["body"] - assert res["headers"]["Content-Type"] == "application/json" - sys.exit(1) - - p = proxy.Proxy(self.conf_path) - p.err_on_done = types.MethodType(err_on_done, p) - with self.assertRaises(SystemExit): - p.read_conf("tests/files/invalid_yaml.yaml") - - def test_config_file_open_generic_exception(self): - def err_on_done(self): - res = self.res.__dict__ - assert res["status"] == 500 - assert res["headers"]["Content-Type"] == "application/json" - sys.exit(1) - - p = proxy.Proxy(self.conf_path) - p.err_on_done = types.MethodType(err_on_done, p) - - with self.assertRaises(SystemExit): - # Patching open so that we can simulate a non-YAML error - # (e.g. permissions) - with patch("builtins.open", side_effect=IOError): - p.read_conf("tests/files/valid-config.yaml") - - def test_config_has_valid_keys(self): - p = proxy.Proxy("tests/files/valid-config.yaml") - - # Verify we have a valid Conf object - self.assertEqual(p.conf.host, "jsonplaceholder.typicode.com") - self.assertEqual(p.conf.port, 443) - self.assertFalse(p.conf.dev) - self.assertEqual(p.conf.scheme, "https") - self.assertEqual(p.conf.target_vm, "compost") - - def test_config_500_when_missing_a_required_key(self): - def err_on_done(self): - res = self.res.__dict__ - assert res["status"] == 500 - assert "missing required keys" in res["body"] - assert res["headers"]["Content-Type"] == "application/json" - sys.exit(1) - - p = proxy.Proxy(self.conf_path) - p.err_on_done = types.MethodType(err_on_done, p) - - with self.assertRaises(SystemExit): - p.read_conf("tests/files/missing-key.yaml") - - def test_config_500_when_missing_target_vm(self): - def err_on_done(self): - res = self.res.__dict__ - assert res["status"] == 500 - assert "missing `target_vm` key" in res["body"] - assert res["headers"]["Content-Type"] == "application/json" - sys.exit(1) - - p = proxy.Proxy(self.conf_path) - p.err_on_done = types.MethodType(err_on_done, p) - - with self.assertRaises(SystemExit): - p.read_conf("tests/files/missing-target-vm.yaml") - - def test_dev_config(self): - p = proxy.Proxy("tests/files/dev-config.yaml") - assert p.conf.dev +import time + +import pytest + + +def test_json_response(proxy_request): + """test a JSON response""" + test_input = { + "method": "GET", + "path_query": "/json", + "stream": False, + } + result = proxy_request(input=test_input) + assert result.returncode == 0 + response = json.loads(result.stdout.decode()) + assert response["status"] == 200 + assert response["headers"]["content-type"] == "application/json" + + +@pytest.mark.parametrize("status_code", (200, 404, 503)) +def test_status_codes(proxy_request, status_code): + """HTTP errors are passed through cleanly""" + test_input = { + "method": "GET", + "path_query": f"/status/{status_code}", + "stream": False, + } + result = proxy_request(input=test_input) + assert result.returncode == 0 + response = json.loads(result.stdout.decode()) + assert response["status"] == status_code + + +def test_query_parameters(proxy_request): + test_input = { + "method": "GET", + "path_query": "/get?foo=bar", + "stream": False, + } + result = proxy_request(input=test_input) + assert result.returncode == 0 + response = json.loads(result.stdout.decode()) + assert response["status"] == 200 + body = json.loads(response["body"]) + assert body["args"] == {"foo": "bar"} + + +def test_timeout(proxy_request, httpbin): + start = time.time() + test_input = {"method": "GET", "path_query": "/delay/10", "stream": False, "timeout": 1} + result = proxy_request(input=test_input) + assert result.returncode == 1 + assert ( + result.stderr.decode().strip() + == '{"error":"error sending request for url (http://127.0.0.1:%s/delay/10): ' % httpbin.port + + 'operation timed out"}' + ) + end = time.time() + # timeout was 1s, so let's graciously say this test needs to complete in less than 3 seconds + assert (end - start) < 3 + + +def test_streaming(proxy_request): + count = 20 + test_input = { + "method": "GET", + "path_query": f"/drip?duration=5&numbytes={count}&code=200&delay=0", + "stream": True, + "timeout": 20, # sec + } + result = proxy_request(input=test_input) + assert result.returncode == 0 + stderr = json.loads(result.stderr.decode()) + assert "headers" in stderr.keys() + assert result.stdout.decode() == "*" * count + + +def test_non_json_response(proxy_request): + test_input = {"method": "GET", "path_query": "/html", "stream": True} + result = proxy_request(input=test_input) + assert result.returncode == 0 + stderr = json.loads(result.stderr.decode()) + assert "headers" in stderr.keys() + assert result.stdout.decode().splitlines()[0] == "" + + +def test_headers(proxy_request): + test_input = { + "method": "GET", + "path_query": "/headers", + "stream": False, + "headers": {"X-Test-Header": "th"}, + } + + result = proxy_request(input=test_input) + assert result.returncode == 0 + response = json.loads(result.stdout.decode()) + assert response["status"] == 200 + body = json.loads(response["body"]) + assert body["headers"]["X-Test-Header"] == "th" + + +def test_body(proxy_request): + body_input = {"id": 42, "title": "test"} + test_input = { + "method": "POST", + "path_query": "/post", + "stream": False, + "body": json.dumps(body_input), + } + + result = proxy_request(input=test_input) + assert result.returncode == 0 + response = json.loads(result.stdout.decode()) + assert response["status"] == 200 + body = json.loads(response["body"]) + assert body["json"] == body_input diff --git a/proxy/wrapper.h b/proxy/wrapper.h new file mode 100644 index 000000000..af61205c7 --- /dev/null +++ b/proxy/wrapper.h @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/scripts/Dockerfile b/scripts/Dockerfile index b06a5c85c..d3535d28b 100644 --- a/scripts/Dockerfile +++ b/scripts/Dockerfile @@ -1,6 +1,9 @@ ARG DISTRO=bullseye FROM debian:$DISTRO +# ARGs must be repeated for every different build stage +ARG DISTRO + ENV PIP_DISABLE_PIP_VERSION_CHECK=1 ENV PIP_PROGRESS_BAR=off ENV CARGO_TERM_COLOR=never @@ -8,6 +11,9 @@ ENV CARGO_TERM_PROGRESS_WHEN=never RUN apt-get update && apt-get --yes upgrade && apt-get install --yes build-essential curl +RUN echo "deb [arch=amd64] https://deb.qubes-os.org/r4.1/vm ${DISTRO} main" > /etc/apt/sources.list.d/qubes.list +COPY qubes-archive-keyring.gpg /etc/apt/trusted.gpg.d/ + # Keep in sync with rust-toolchain.toml ENV RUST_VERSION 1.74.1 ENV RUSTUP_VERSION 1.24.3 diff --git a/scripts/qubes-archive-keyring.gpg b/scripts/qubes-archive-keyring.gpg new file mode 100644 index 000000000..7a2d634b3 Binary files /dev/null and b/scripts/qubes-archive-keyring.gpg differ diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml index 2772ccb21..076bba173 100644 --- a/supply-chain/audits.toml +++ b/supply-chain/audits.toml @@ -1,4 +1,214 @@ # cargo-vet audits file -[audits] +[[audits.crc32fast]] +who = "Kunal Mehta " +criteria = "safe-to-run" +delta = "1.3.2 -> 1.4.0" + +[[audits.gimli]] +who = "Kunal Mehta " +criteria = "safe-to-run" +delta = "0.28.0 -> 0.28.1" + +[[audits.mime]] +who = "Kunal Mehta " +criteria = "safe-to-run" +delta = "0.3.16 -> 0.3.17" + +[[audits.miniz_oxide]] +who = "Kunal Mehta " +criteria = "safe-to-run" +delta = "0.7.1 -> 0.7.2" + +[[audits.mio]] +who = "Kunal Mehta " +criteria = "safe-to-run" +delta = "0.8.8 -> 0.8.10" +notes = "mostly adding more platform support, the added unsafe code was pre-existing and just relocated" + +[[audits.rustls-pemfile]] +who = "Kunal Mehta " +criteria = "safe-to-run" +version = "1.0.4" +notes = "code is fine, cannot vouch for correctness though" + +[[audits.slab]] +who = "Kunal Mehta " +criteria = "safe-to-run" +delta = "0.4.8 -> 0.4.9" + +[[audits.socket2]] +who = "Kunal Mehta " +criteria = "safe-to-run" +delta = "0.4.9 -> 0.4.4" + +[[audits.sync_wrapper]] +who = "Kunal Mehta " +criteria = "safe-to-run" +delta = "0.1.1 -> 0.1.2" + +[[audits.tempfile]] +who = "Kunal Mehta " +criteria = "safe-to-run" +delta = "3.9.0 -> 3.10.0" + +[[audits.tracing]] +who = "Kunal Mehta " +criteria = "safe-to-run" +delta = "0.1.37 -> 0.1.40" +notes = "new unsafe usages are all documented" + +[[trusted.flate2]] +criteria = "safe-to-deploy" +user-id = 4333 +start = "2020-09-30" +end = "2024-08-12" +notes = "Rust Project member" + +[[trusted.flate2]] +criteria = "safe-to-deploy" +user-id = 980 # Sebastian Thiel (Byron) +start = "2023-08-15" +end = "2024-08-29" +notes = "Rust Project member" + +[[trusted.futures-io]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2020-10-05" +end = "2024-08-29" +notes = "Rust Project member" + +[[trusted.futures-macro]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2020-10-05" +end = "2024-08-29" +notes = "Rust Project member" + +[[trusted.futures-sink]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2020-10-05" +end = "2024-08-29" +notes = "Rust Project member" + +[[trusted.indexmap]] +criteria = "safe-to-deploy" +user-id = 539 # Josh Stone (cuviper) +start = "2020-01-15" +end = "2024-08-12" +notes = "Rust Project member" + +[[trusted.libc]] +criteria = "safe-to-deploy" +user-id = 51017 # Yuki Okushi (JohnTitor) +start = "2020-03-17" +end = "2024-08-12" +notes = "Rust Project member" + +[[trusted.linux-raw-sys]] +criteria = "safe-to-deploy" +user-id = 6825 # Dan Gohman (sunfishcode) +start = "2021-06-12" +end = "2024-08-12" +notes = "Rust Project member" + +[[trusted.mio]] +criteria = "safe-to-deploy" +user-id = 10 # Carl Lerche (carllerche) +start = "2019-05-15" +end = "2024-08-12" +notes = "Rust Project member" + +[[trusted.openssl]] +criteria = "safe-to-deploy" +user-id = 163 # Alex Gaynor (alex) +start = "2023-03-24" +end = "2024-08-12" +notes = "Rust Project member" + +[[trusted.openssl-sys]] +criteria = "safe-to-deploy" +user-id = 163 # Alex Gaynor (alex) +start = "2023-03-24" +end = "2024-08-12" +notes = "Rust Project member" + +[[trusted.proc-macro2]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-04-23" +end = "2024-08-12" +notes = "Rust Project member" + +[[trusted.rustix]] +criteria = "safe-to-deploy" +user-id = 6825 # Dan Gohman (sunfishcode) +start = "2021-10-29" +end = "2024-08-12" +notes = "Rust Project member" + +[[trusted.ryu]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-05-02" +end = "2024-08-12" +notes = "Rust Project member" + +[[trusted.serde]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-03-01" +end = "2024-08-12" +notes = "Rust Project member" + +[[trusted.serde_derive]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-03-01" +end = "2024-08-12" +notes = "Rust Project member" + +[[trusted.serde_json]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-02-28" +end = "2024-08-12" +notes = "Rust Project member" + +[[trusted.slab]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2021-04-20" +end = "2024-08-29" +notes = "Rust Project member" + +[[trusted.socket2]] +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2019-05-06" +end = "2024-08-12" +notes = "Rust Project member" + +[[trusted.syn]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-03-01" +end = "2024-08-12" +notes = "Rust Project member" + +[[trusted.tokio-macros]] +criteria = "safe-to-deploy" +user-id = 10 # Carl Lerche (carllerche) +start = "2019-04-24" +end = "2024-08-12" +notes = "Rust Project member" + +[[trusted.wasm-bindgen-futures]] +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2019-03-04" +end = "2024-08-12" +notes = "Rust Project member" diff --git a/supply-chain/config.toml b/supply-chain/config.toml index ab67610e6..5751a8ff9 100644 --- a/supply-chain/config.toml +++ b/supply-chain/config.toml @@ -22,5 +22,101 @@ url = "https://raw.githubusercontent.com/freedomofpress/securedrop-supply-chain/ [imports.zcash] url = "https://raw.githubusercontent.com/zcash/rust-ecosystem/main/supply-chain/audits.toml" +[policy.js-sys] +criteria = [] +notes = "WASM-only" + +[policy.schannel] +criteria = [] +notes = "Windows-only" + [policy.securedrop-proxy] criteria = "safe-to-run" + +[policy.security-framework] +criteria = [] +notes = "macOS-only" + +[policy.security-framework-sys] +criteria = [] +notes = "macOS-only" + +[policy.system-configuration] +criteria = [] +notes = "macOS-only" + +[policy.system-configuration-sys] +criteria = [] +notes = "macOS-only" + +[policy.wasi] +criteria = [] +notes = "WASM-only" + +[policy.wasm-bindgen] +criteria = [] +notes = "WASM-only" + +[policy.wasm-bindgen-backend] +criteria = [] +notes = "WASM-only" + +[policy.wasm-bindgen-macro] +criteria = [] +notes = "WASM-only" + +[policy.wasm-bindgen-macro-support] +criteria = [] +notes = "WASM-only" + +[policy.wasm-bindgen-shared] +criteria = [] +notes = "WASM-only" + +[policy.wasm-streams] +criteria = [] +notes = "WASM-only" + +[policy.web-sys] +criteria = [] +notes = "WASM-only" + +[policy.windows-sys] +criteria = [] +notes = "Windows-only" + +[policy.windows-targets] +criteria = [] +notes = "Windows-only" + +[policy.windows_aarch64_gnullvm] +criteria = [] +notes = "Windows-only" + +[policy.windows_aarch64_msvc] +criteria = [] +notes = "Windows-only" + +[policy.windows_i686_gnu] +criteria = [] +notes = "Windows-only" + +[policy.windows_i686_msvc] +criteria = [] +notes = "Windows-only" + +[policy.windows_x86_64_gnu] +criteria = [] +notes = "Windows-only" + +[policy.windows_x86_64_gnullvm] +criteria = [] +notes = "Windows-only" + +[policy.windows_x86_64_msvc] +criteria = [] +notes = "Windows-only" + +[policy.winreg] +criteria = [] +notes = "Windows-only" diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index 916aeb90e..b3d8a08a7 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -1,14 +1,1165 @@ # cargo-vet imports lock -[audits.bytecode-alliance.audits] +[[publisher.core-foundation-sys]] +version = "0.8.4" +when = "2023-04-03" +user-id = 5946 +user-login = "jrmuizel" +user-name = "Jeff Muizelaar" -[audits.google.audits] +[[publisher.encoding_rs]] +version = "0.8.33" +when = "2023-08-23" +user-id = 4484 +user-login = "hsivonen" +user-name = "Henri Sivonen" -[audits.isrg.audits] +[[publisher.flate2]] +version = "1.0.28" +when = "2023-10-13" +user-id = 980 +user-login = "Byron" +user-name = "Sebastian Thiel" -[audits.mozilla.audits] +[[publisher.futures-io]] +version = "0.3.30" +when = "2023-12-24" +user-id = 33035 +user-login = "taiki-e" +user-name = "Taiki Endo" -[audits.securedrop.audits] +[[publisher.futures-macro]] +version = "0.3.30" +when = "2023-12-24" +user-id = 33035 +user-login = "taiki-e" +user-name = "Taiki Endo" -[audits.zcash.audits] +[[publisher.futures-sink]] +version = "0.3.30" +when = "2023-12-24" +user-id = 33035 +user-login = "taiki-e" +user-name = "Taiki Endo" + +[[publisher.indexmap]] +version = "2.2.3" +when = "2024-02-11" +user-id = 539 +user-login = "cuviper" +user-name = "Josh Stone" + +[[publisher.libc]] +version = "0.2.153" +when = "2024-01-31" +user-id = 51017 +user-login = "JohnTitor" +user-name = "Yuki Okushi" + +[[publisher.linux-raw-sys]] +version = "0.4.13" +when = "2024-01-16" +user-id = 6825 +user-login = "sunfishcode" +user-name = "Dan Gohman" + +[[publisher.openssl]] +version = "0.10.63" +when = "2024-01-20" +user-id = 163 +user-login = "alex" +user-name = "Alex Gaynor" + +[[publisher.openssl-sys]] +version = "0.9.99" +when = "2024-01-20" +user-id = 163 +user-login = "alex" +user-name = "Alex Gaynor" + +[[publisher.proc-macro2]] +version = "1.0.78" +when = "2024-01-21" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.rustix]] +version = "0.38.31" +when = "2024-02-01" +user-id = 6825 +user-login = "sunfishcode" +user-name = "Dan Gohman" + +[[publisher.ryu]] +version = "1.0.16" +when = "2023-12-09" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.serde]] +version = "1.0.196" +when = "2024-01-26" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.serde_derive]] +version = "1.0.196" +when = "2024-01-26" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.serde_json]] +version = "1.0.113" +when = "2024-01-29" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.syn]] +version = "2.0.48" +when = "2024-01-04" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.tokio-macros]] +version = "2.2.0" +when = "2023-11-09" +user-id = 10 +user-login = "carllerche" +user-name = "Carl Lerche" + +[[publisher.wasm-bindgen-futures]] +version = "0.4.41" +when = "2024-02-06" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + +[[audits.bytecode-alliance.audits.addr2line]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.19.0 -> 0.20.0" +notes = "This version brings support for split-dwarf which while it uses the filesystem is always done at the behest of the caller, so everything is as expected for this update." + +[[audits.bytecode-alliance.audits.addr2line]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.20.0 -> 0.21.0" +notes = "This version bump updated some dependencies and optimized some internals. All looks good." + +[[audits.bytecode-alliance.audits.adler]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "1.0.2" +notes = "This is a small crate which forbids unsafe code and is a straightforward implementation of the adler hashing algorithm." + +[[audits.bytecode-alliance.audits.anyhow]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +delta = "1.0.69 -> 1.0.71" + +[[audits.bytecode-alliance.audits.base64]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.21.0" +notes = "This crate has no dependencies, no build.rs, and contains no unsafe code." + +[[audits.bytecode-alliance.audits.cc]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "1.0.73" +notes = "I am the author of this crate." + +[[audits.bytecode-alliance.audits.cfg-if]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "1.0.0" +notes = "I am the author of this crate." + +[[audits.bytecode-alliance.audits.core-foundation-sys]] +who = "Dan Gohman " +criteria = "safe-to-deploy" +delta = "0.8.4 -> 0.8.6" +notes = """ +The changes here are all typical bindings updates: new functions, types, and +constants. I have not audited all the bindings for ABI conformance. +""" + +[[audits.bytecode-alliance.audits.fastrand]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "2.0.0 -> 2.0.1" +notes = """ +This update had a few doc updates but no otherwise-substantial source code +updates. +""" + +[[audits.bytecode-alliance.audits.foreign-types]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.3.2" +notes = "This crate defined a macro-rules which creates wrappers working with FFI types. The implementation of this crate appears to be safe, but each use of this macro would need to be vetted for correctness as well." + +[[audits.bytecode-alliance.audits.foreign-types-shared]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.1.1" + +[[audits.bytecode-alliance.audits.gimli]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.27.3 -> 0.28.0" +notes = """ +Still looks like a good DWARF-parsing crate, nothing major was added or deleted +and no `unsafe` code to review here. +""" + +[[audits.bytecode-alliance.audits.http]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.2.9 -> 1.0.0" +notes = "Minor changes leading up to the 1.0.0 release and nothing fundamentally new here." + +[[audits.bytecode-alliance.audits.idna]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "0.3.0" +notes = """ +This is a crate without unsafe code or usage of the standard library. The large +size of this crate comes from the large generated unicode tables file. This +crate is broadly used throughout the ecosystem and does not contain anything +suspicious. +""" + +[[audits.bytecode-alliance.audits.miniz_oxide]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "0.7.1" +notes = """ +This crate is a Rust implementation of zlib compression/decompression and has +been used by default by the Rust standard library for quite some time. It's also +a default dependency of the popular `backtrace` crate for decompressing debug +information. This crate forbids unsafe code and does not otherwise access system +resources. It's originally a port of the `miniz.c` library as well, and given +its own longevity should be relatively hardened against some of the more common +compression-related issues. +""" + +[[audits.bytecode-alliance.audits.native-tls]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.2.11" +notes = "build is only looking for environment variables to set cfg. only two minor uses of unsafe,on macos, with ffi bindings to digest primitives and libc atexit. otherwise, this is an abstraction over three very complex systems (schannel, security-framework, and openssl) which may end up having subtle differences, but none of those are apparent from the implementation of this crate" + +[[audits.bytecode-alliance.audits.openssl-macros]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.1.0" + +[[audits.bytecode-alliance.audits.openssl-probe]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.1.5" +notes = "IO is only checking for the existence of paths in the filesystem" + +[[audits.bytecode-alliance.audits.percent-encoding]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "2.2.0" +notes = """ +This crate is a single-file crate that does what it says on the tin. There are +a few `unsafe` blocks related to utf-8 validation which are locally verifiable +as correct and otherwise this crate is good to go. +""" + +[[audits.bytecode-alliance.audits.pin-utils]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.1.0" + +[[audits.bytecode-alliance.audits.pkg-config]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.3.26 -> 0.3.29" +notes = """ +No `unsafe` additions or anything outside of the purview of the crate in this +change. +""" + +[[audits.bytecode-alliance.audits.rustc-demangle]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "0.1.21" +notes = "I am the author of this crate." + +[[audits.bytecode-alliance.audits.tempfile]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "3.5.0 -> 3.6.0" +notes = "Dependency updates and new optimized trait implementations, but otherwise everything looks normal." + +[[audits.bytecode-alliance.audits.tinyvec]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "1.6.0" +notes = """ +This crate, while it implements collections, does so without `std::*` APIs and +without `unsafe`. Skimming the crate everything looks reasonable and what one +would expect from idiomatic safe collections in Rust. +""" + +[[audits.bytecode-alliance.audits.tinyvec_macros]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "0.1.0" +notes = """ +This is a trivial crate which only contains a singular macro definition which is +intended to multiplex across the internal representation of a tinyvec, +presumably. This trivially doesn't contain anything bad. +""" + +[[audits.bytecode-alliance.audits.tokio-native-tls]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.3.1" +notes = "unsafety is used for smuggling std::task::Context as a raw pointer. Lifetime and type safety appears to be taken care of correctly." + +[[audits.bytecode-alliance.audits.try-lock]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.2.4" +notes = "Implements a concurrency primitive with atomics, and is not obviously incorrect" + +[[audits.bytecode-alliance.audits.unicode-bidi]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "0.3.8" +notes = """ +This crate has no unsafe code and does not use `std::*`. Skimming the crate it +does not attempt to out of the bounds of what it's already supposed to be doing. +""" + +[[audits.bytecode-alliance.audits.unicode-ident]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "1.0.8" + +[[audits.bytecode-alliance.audits.vcpkg]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.2.15" +notes = "no build.rs, no macros, no unsafe. It reads the filesystem and makes copies of DLLs into OUT_DIR." + +[[audits.bytecode-alliance.audits.want]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.3.0" + +[[audits.google.audits.addr2line]] +who = "George Burgess IV " +criteria = "safe-to-run" +version = "0.19.0" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.anyhow]] +who = "ChromeOS" +criteria = "safe-to-run" +version = "1.0.68" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.backtrace]] +who = "George Burgess IV " +criteria = "safe-to-run" +version = "0.3.67" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.bitflags]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +version = "2.4.2" +notes = """ +Audit notes: + +* I've checked for any discussion in Google-internal cl/546819168 (where audit + of version 2.3.3 happened) +* `src/lib.rs` contains `#![cfg_attr(not(test), forbid(unsafe_code))]` +* There are 2 cases of `unsafe` in `src/external.rs` but they seem to be + correct in a straightforward way - they just propagate the marker trait's + impl (e.g. `impl bytemuck::Pod`) from the inner to the outer type +* Additional discussion and/or notes may be found in https://crrev.com/c/5238056 +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.bytes]] +who = "George Burgess IV " +criteria = "safe-to-run" +version = "1.4.0" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.equivalent]] +who = "George Burgess IV " +criteria = "safe-to-deploy" +version = "1.0.1" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.errno]] +who = "George Burgess IV " +criteria = "safe-to-run" +version = "0.2.8" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.errno]] +who = "George Burgess IV " +criteria = "safe-to-run" +delta = "0.2.8 -> 0.3.1" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.fastrand]] +who = "George Burgess IV " +criteria = "safe-to-deploy" +version = "1.9.0" +notes = """ +`does-not-implement-crypto` is certified because this crate explicitly says +that the RNG here is not cryptographically secure. +""" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.futures-channel]] +who = "George Burgess IV " +criteria = "safe-to-run" +version = "0.3.28" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.futures-core]] +who = "George Burgess IV " +criteria = "safe-to-run" +version = "0.3.28" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.futures-task]] +who = "George Burgess IV " +criteria = "safe-to-run" +version = "0.3.28" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.futures-util]] +who = "George Burgess IV " +criteria = "safe-to-run" +version = "0.3.28" +notes = """ +There's a custom xorshift-based `random::shuffle` implementation in +src/async_await/random.rs. This is `doc(hidden)` and seems to exist just so +that `futures-macro::select` can be unbiased. Sicne xorshift is explicitly not +intended to be a cryptographically secure algorithm, it is not considered +crypto. +""" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.gimli]] +who = "George Burgess IV " +criteria = "safe-to-run" +version = "0.27.3" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.h2]] +who = "George Burgess IV " +criteria = "safe-to-run" +version = "0.3.18" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.h2]] +who = "George Burgess IV " +criteria = "safe-to-run" +delta = "0.3.18 -> 0.3.19" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.h2]] +who = "George Burgess IV " +criteria = "safe-to-run" +delta = "0.3.19 -> 0.3.20" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.h2]] +who = "George Burgess IV " +criteria = "safe-to-run" +delta = "0.3.20 -> 0.3.21" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.h2]] +who = "George Burgess IV " +criteria = "safe-to-run" +delta = "0.3.21 -> 0.3.24" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.hashbrown]] +who = "Nicholas Bishop " +criteria = "safe-to-run" +version = "0.13.2" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.hashbrown]] +who = "George Burgess IV " +criteria = "safe-to-run" +delta = "0.13.2 -> 0.14.3" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.http]] +who = "George Burgess IV " +criteria = "safe-to-run" +version = "0.2.9" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.http-body]] +who = "ChromeOS" +criteria = "safe-to-run" +version = "0.4.5" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.httparse]] +who = "George Burgess IV " +criteria = "safe-to-run" +version = "1.8.0" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.httpdate]] +who = "George Burgess IV " +criteria = "safe-to-deploy" +version = "1.0.3" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.hyper]] +who = "George Burgess IV " +criteria = "safe-to-run" +version = "0.14.27" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.itoa]] +who = "ChromeOS" +criteria = "safe-to-run" +version = "1.0.5" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.itoa]] +who = "George Burgess IV " +criteria = "safe-to-run" +delta = "1.0.5 -> 1.0.6" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.itoa]] +who = "George Burgess IV " +criteria = "safe-to-run" +delta = "1.0.6 -> 1.0.9" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.lazy_static]] +who = "Android Legacy" +criteria = "safe-to-run" +version = "1.4.0" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.log]] +who = "ChromeOS" +criteria = "safe-to-run" +version = "0.4.17" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.log]] +who = "George Burgess IV " +criteria = "safe-to-run" +delta = "0.4.17 -> 0.4.20" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.memchr]] +who = "George Burgess IV " +criteria = "safe-to-run" +version = "2.6.3" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.mime]] +who = "ChromeOS" +criteria = "safe-to-run" +version = "0.3.16" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.mio]] +who = "Vovo Yang " +criteria = "safe-to-run" +version = "0.8.8" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.once_cell]] +who = "crosvm" +criteria = "safe-to-run" +version = "1.17.0" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.once_cell]] +who = "George Burgess IV " +criteria = "safe-to-run" +delta = "1.17.0 -> 1.18.0" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.openssl-macros]] +who = "George Burgess IV " +criteria = "safe-to-deploy" +delta = "0.1.0 -> 0.1.1" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.percent-encoding]] +who = "George Burgess IV " +criteria = "safe-to-run" +delta = "2.2.0 -> 2.3.0" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.pin-project-lite]] +who = "ChromeOS" +criteria = "safe-to-run" +version = "0.2.9" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.pin-project-lite]] +who = "David Koloski " +criteria = "safe-to-deploy" +delta = "0.2.9 -> 0.2.13" +notes = "Audited at https://fxrev.dev/946396" +aggregated-from = "https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/third_party/rust_crates/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.pkg-config]] +who = "Alexandre Courbot " +criteria = "safe-to-run" +version = "0.3.26" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.quote]] +who = "ChromeOS" +criteria = "safe-to-run" +version = "1.0.23" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.quote]] +who = "George Burgess IV " +criteria = "safe-to-run" +delta = "1.0.23 -> 1.0.26" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.quote]] +who = "George Burgess IV " +criteria = "safe-to-run" +delta = "1.0.26 -> 1.0.28" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.quote]] +who = "George Burgess IV " +criteria = "safe-to-run" +delta = "1.0.28 -> 1.0.31" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.serde_urlencoded]] +who = "ChromeOS" +criteria = "safe-to-run" +version = "0.7.1" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.slab]] +who = "Android Legacy" +criteria = "safe-to-run" +version = "0.4.7" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.socket2]] +who = "Vovo Yang " +criteria = "safe-to-run" +version = "0.4.9" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.socket2]] +who = "David Koloski " +criteria = "safe-to-deploy" +delta = "0.4.4 -> 0.5.5" +notes = "Reviewed at https://fxrev.dev/946307" +aggregated-from = "https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/third_party/rust_crates/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.sync_wrapper]] +who = "ChromeOS" +criteria = "safe-to-run" +version = "0.1.1" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.tempfile]] +who = "George Burgess IV " +criteria = "safe-to-run" +version = "3.4.0" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.tower-service]] +who = "ChromeOS" +criteria = "safe-to-run" +version = "0.3.2" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.tracing]] +who = "ChromeOS" +criteria = "safe-to-run" +version = "0.1.35" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.tracing-core]] +who = "ChromeOS" +criteria = "safe-to-run" +version = "0.1.29" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.unicode-normalization]] +who = "George Burgess IV " +criteria = "safe-to-run" +version = "0.1.22" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.isrg.audits.base64]] +who = "Tim Geoghegan " +criteria = "safe-to-deploy" +delta = "0.21.0 -> 0.21.1" + +[[audits.isrg.audits.base64]] +who = "Brandon Pitman " +criteria = "safe-to-deploy" +delta = "0.21.1 -> 0.21.2" + +[[audits.isrg.audits.base64]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.21.2 -> 0.21.3" + +[[audits.isrg.audits.base64]] +who = "Ameer Ghani " +criteria = "safe-to-run" +delta = "0.21.3 -> 0.21.4" + +[[audits.isrg.audits.base64]] +who = "David Cook " +criteria = "safe-to-run" +delta = "0.21.4 -> 0.21.5" + +[[audits.isrg.audits.base64]] +who = "Brandon Pitman " +criteria = "safe-to-run" +delta = "0.21.5 -> 0.21.6" +notes = "sourcegraph-based diff did not see the v0.21.6 tag; I retrieved a local copy of the repo and used that for diff'ing." + +[[audits.isrg.audits.base64]] +who = "David Cook " +criteria = "safe-to-run" +delta = "0.21.6 -> 0.21.7" + +[[audits.isrg.audits.once_cell]] +who = "Brandon Pitman " +criteria = "safe-to-deploy" +delta = "1.18.0 -> 1.19.0" + +[[audits.mozilla.wildcard-audits.core-foundation-sys]] +who = "Bobby Holley " +criteria = "safe-to-deploy" +user-id = 5946 # Jeff Muizelaar (jrmuizel) +start = "2020-10-14" +end = "2023-05-04" +renew = false +notes = "I've reviewed every source contribution that was neither authored nor reviewed by Mozilla." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.wildcard-audits.encoding_rs]] +who = "Henri Sivonen " +criteria = "safe-to-deploy" +user-id = 4484 # Henri Sivonen (hsivonen) +start = "2019-02-26" +end = "2024-08-28" +notes = "I, Henri Sivonen, wrote encoding_rs for Gecko and have reviewed contributions by others. There are two caveats to the certification: 1) The crate does things that are documented to be UB but that do not appear to actually be UB due to integer types differing from the general rule; https://github.com/hsivonen/encoding_rs/issues/79 . 2) It would be prudent to re-review the code that reinterprets buffers of integers as SIMD vectors; see https://github.com/hsivonen/encoding_rs/issues/87 ." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.anyhow]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "1.0.68 -> 1.0.69" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.autocfg]] +who = "Josh Stone " +criteria = "safe-to-deploy" +version = "1.1.0" +notes = "All code written or reviewed by Josh Stone." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.errno]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.3.1 -> 0.3.3" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.fastrand]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "1.9.0 -> 2.0.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.fnv]] +who = "Bobby Holley " +criteria = "safe-to-deploy" +version = "1.0.7" +notes = "Simple hasher implementation with no unsafe code." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.form_urlencoded]] +who = "Valentin Gosu " +criteria = "safe-to-deploy" +version = "1.2.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.form_urlencoded]] +who = "Valentin Gosu " +criteria = "safe-to-deploy" +delta = "1.2.0 -> 1.2.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.idna]] +who = "Valentin Gosu " +criteria = "safe-to-deploy" +delta = "0.4.0 -> 0.5.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.percent-encoding]] +who = "Valentin Gosu " +criteria = "safe-to-deploy" +delta = "2.3.0 -> 2.3.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.slab]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.4.7 -> 0.4.8" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.tempfile]] +who = "Jan-Erik Rediger " +criteria = "safe-to-deploy" +delta = "3.4.0 -> 3.5.0" +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.tempfile]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "3.6.0 -> 3.8.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.tempfile]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "3.8.0 -> 3.9.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.tracing]] +who = "Mike Hommey " +criteria = "safe-to-run" +delta = "0.1.35 -> 0.1.36" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.tracing]] +who = "Mike Hommey " +criteria = "safe-to-run" +delta = "0.1.36 -> 0.1.37" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.tracing-core]] +who = "Mike Hommey " +criteria = "safe-to-run" +delta = "0.1.29 -> 0.1.30" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.unicode-bidi]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "0.3.8 -> 0.3.13" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.unicode-bidi]] +who = "Jonathan Kew " +criteria = "safe-to-deploy" +delta = "0.3.13 -> 0.3.14" +notes = "I am the author of the bulk of the upstream changes in this version, and also checked the remaining post-0.3.13 changes." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.unicode-bidi]] +who = "Jonathan Kew " +criteria = "safe-to-deploy" +delta = "0.3.14 -> 0.3.15" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.unicode-ident]] +who = "Jan-Erik Rediger " +criteria = "safe-to-deploy" +delta = "1.0.8 -> 1.0.9" +notes = "Dependency updates only" +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.url]] +who = "Valentin Gosu " +criteria = "safe-to-deploy" +version = "2.4.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.url]] +who = "Valentin Gosu " +criteria = "safe-to-deploy" +delta = "2.4.0 -> 2.4.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.url]] +who = "Valentin Gosu " +criteria = "safe-to-deploy" +delta = "2.4.1 -> 2.5.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.securedrop.audits.cc]] +who = "Cory Francis Myers " +criteria = "safe-to-run" +delta = "1.0.73 -> 1.0.83" +aggregated-from = "https://raw.githubusercontent.com/freedomofpress/securedrop/develop/supply-chain/audits.toml" + +[[audits.securedrop.audits.crc32fast]] +who = "Cory Francis Myers " +criteria = "safe-to-run" +version = "1.3.2" +aggregated-from = "https://raw.githubusercontent.com/freedomofpress/securedrop/develop/supply-chain/audits.toml" + +[[audits.securedrop.audits.idna]] +who = "Kunal Mehta " +criteria = "safe-to-run" +delta = "0.3.0 -> 0.4.0" +notes = "Primarily adding a no_std mode" +aggregated-from = "https://raw.githubusercontent.com/freedomofpress/securedrop/develop/supply-chain/audits.toml" + +[[audits.zcash.audits.anyhow]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "1.0.71 -> 1.0.75" +notes = """ +`unsafe` changes are migrating from `core::any::Demand` to `std::error::Request` when the +nightly features are available. +""" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.backtrace]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.67 -> 0.3.69" +notes = """ +Changes to `unsafe` blocks: +- New call to `GetCurrentProcessId` on Windows, to help generate a process-unique name to + use inside an existing `CreateMutexA` call. +- Uses `libc::mmap64` on Linux instead of `libc::mmap`. +- Alters `Stash` to allow caching more than one `Mmap`; the existing `unsafe` safety + condition continues to be applicable. + +There are also several more places where DWARF data is mmapped from a filesystem path and +then loaded. These appear to all derive from existing paths that themselves were already +being mmapped and loaded. +""" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.bytes]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "1.4.0 -> 1.5.0" +notes = """ +- Introduces new `unsafe` blocks inside new `UninitSlice` constructors, but these replace + existing equivalent `unsafe` blocks that were directly constructing `UninitSlice`. +- Adds `unsafe impl BufMut for &mut [core::mem::MaybeUninit]`, which is implemented + almost identically to the existing `unsafe impl BufMut for &mut [u8]`. +""" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.errno]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.3 -> 0.3.8" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.futures-channel]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.28 -> 0.3.29" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.futures-channel]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.29 -> 0.3.30" +notes = "Removes `build.rs` now that it can rely on the `target_has_atomic` attribute." +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.futures-core]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.28 -> 0.3.29" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.futures-core]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.29 -> 0.3.30" +notes = "Removes `build.rs` now that it can rely on the `target_has_atomic` attribute." +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.futures-task]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.28 -> 0.3.29" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.futures-task]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.29 -> 0.3.30" +notes = "Removes `build.rs` now that it can rely on the `target_has_atomic` attribute." +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.futures-util]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.28 -> 0.3.29" +notes = """ +Only change to `unsafe` code is to add a `Fut: Send` bound to the +`unsafe impl Sync for FuturesUnordered`. +""" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.futures-util]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.29 -> 0.3.30" +notes = """ +- Removes `build.rs` now that it can rely on the `target_has_atomic` attribute. +- Almost all changes to `unsafe` blocks are to either move them around, or + replace them with safe method calls. +- One new `unsafe` block is added for a slice lifetime transmutation. The slice + reconstruction is obviously correct. AFAICT the lifetime transmutation is also + correct; the slice's lifetime logically comes from the `AsyncBufRead` reader + inside `FillBuf`, rather than the `Context`. +""" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.http]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "1.0.0 -> 0.2.11" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.http-body]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.4.5 -> 0.4.6" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.hyper]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.14.27 -> 0.14.28" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.itoa]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "1.0.9 -> 1.0.10" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.memchr]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "2.6.3 -> 2.6.4" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.memchr]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "2.6.4 -> 2.7.1" +notes = """ +Change to an `unsafe fn` is to rework the short-tail handling of a fixed-length +comparison between `u8` pointers. The new tail code matches the existing head +code (but adapted to `u16` and `u8` reads, instead of `u32`). +""" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.quote]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "1.0.31 -> 1.0.33" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.quote]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "1.0.33 -> 1.0.35" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.rustc-demangle]] +who = "Sean Bowe " +criteria = "safe-to-deploy" +delta = "0.1.21 -> 0.1.22" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.rustc-demangle]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.1.22 -> 0.1.23" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.tinyvec_macros]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.1.0 -> 0.1.1" +notes = "Adds `#![forbid(unsafe_code)]` and license files." +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.tracing-core]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.1.30 -> 0.1.31" +notes = """ +The only new `unsafe` block is to intentionally leak a scoped subscriber onto +the heap when setting it as the global default dispatcher. I checked that the +global default can only be set once and is never dropped. +""" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.tracing-core]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.1.31 -> 0.1.32" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.try-lock]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.2.4 -> 0.2.5" +notes = "Bumps MSRV to remove unsafe code block." +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.unicode-ident]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "1.0.9 -> 1.0.12" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.want]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.0 -> 0.3.1" +notes = """ +Migrates to `try-lock 0.2.4` to replace some unsafe APIs that were not marked +`unsafe` (but that were being used safely). +""" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml"