diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 5518d90..1a8ac28 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -16,10 +16,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Install latest nightly + - name: Install rust uses: actions-rs/toolchain@v1 with: - toolchain: nightly + toolchain: stable override: true - name: Run cargo build @@ -31,10 +31,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Install latest nightly + - name: Install rust uses: actions-rs/toolchain@v1 with: - toolchain: nightly + toolchain: stable override: true - name: Run cargo test @@ -46,10 +46,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Install latest nightly + - name: Install latest rust uses: actions-rs/toolchain@v1 with: - toolchain: nightly + toolchain: stable override: true components: clippy @@ -62,10 +62,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Install latest nightly + - name: Install latest rust uses: actions-rs/toolchain@v1 with: - toolchain: nightly + toolchain: stable override: true components: rustfmt diff --git a/Cargo.lock b/Cargo.lock index 24df36e..2f7d6d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,67 +17,23 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "aead" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cf01b9b56e767bb57b94ebf91a58b338002963785cdd7013e21c0d4679471e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "aes" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54eb1d8fe354e5fc611daf4f2ea97dd45a765f4f1e4512306ec183ae2e8f20c9" -dependencies = [ - "aes-soft", - "aesni", - "block-cipher-trait", -] - -[[package]] -name = "aes-gcm" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "834a6bda386024dbb7c8fc51322856c10ffe69559f972261c868485f5759c638" -dependencies = [ - "aead", - "aes", - "block-cipher-trait", - "ghash", - "subtle 2.4.0", - "zeroize", -] - -[[package]] -name = "aes-soft" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" -dependencies = [ - "block-cipher-trait", - "byteorder", - "opaque-debug", -] - -[[package]] -name = "aesni" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" -dependencies = [ - "block-cipher-trait", - "opaque-debug", -] - [[package]] name = "ahash" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" +[[package]] +name = "ahash" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f200cbb1e856866d9eade941cf3aa0c5d7dd36f74311c4273b494f4ef036957" +dependencies = [ + "getrandom 0.2.2", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.15" @@ -93,7 +49,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -108,6 +64,26 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "async-trait" +version = "0.1.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589652ce7ccb335d1e7ecb3be145425702b290dbcb7029bbeaae263fc1d87b48" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atoi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616896e05fc0e2649463a93a15183c6a16bf03413a7af88ef1285ddedfa9cda5" +dependencies = [ + "num-traits 0.2.14", +] + [[package]] name = "atty" version = "0.2.14" @@ -116,35 +92,33 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", - "winapi 0.3.9", + "winapi", ] [[package]] name = "atuin" version = "0.5.0" dependencies = [ - "base64 0.13.0", + "async-trait", + "base64", "chrono", "chrono-english", "cli-table", "config", - "diesel", - "diesel_migrations", "directories", "dotenv", "eyre", "fern", "fork", "human-panic", + "humantime", "indicatif", "itertools", - "log 0.4.14", + "log", "parse_duration", "rand 0.8.3", "reqwest", "rmp-serde", - "rocket", - "rocket_contrib", "rusqlite", "rust-crypto", "serde 1.0.125", @@ -152,11 +126,15 @@ dependencies = [ "serde_json", "shellexpand", "sodiumoxide", + "sqlx", "structopt", "termion", + "tokio", "tui", "unicode-width", + "urlencoding", "uuid", + "warp", "whoami", ] @@ -173,29 +151,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc" dependencies = [ "addr2line", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -dependencies = [ - "byteorder", - "safemem", -] - -[[package]] -name = "base64" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" - [[package]] name = "base64" version = "0.13.0" @@ -208,6 +170,18 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "bitvec" +version = "0.19.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "blake2b_simd" version = "0.5.11" @@ -221,34 +195,13 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.7.3" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array", -] - -[[package]] -name = "block-cipher-trait" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ "generic-array", ] -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", -] - [[package]] name = "bstr" version = "0.2.15" @@ -261,18 +214,28 @@ dependencies = [ "serde 1.0.125", ] +[[package]] +name = "buf_redux" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f" +dependencies = [ + "memchr", + "safemem", +] + +[[package]] +name = "build_const" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" + [[package]] name = "bumpalo" version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - [[package]] name = "byteorder" version = "1.4.2" @@ -297,12 +260,6 @@ version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -320,7 +277,7 @@ dependencies = [ "num-traits 0.2.14", "serde 1.0.125", "time", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -367,9 +324,20 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efe942512e068e15991cbcef4e8182884555febbb21b5b4faf5dd5561850141a" dependencies = [ - "proc-macro2 1.0.26", - "quote 1.0.9", - "syn 1.0.69", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "colored" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" +dependencies = [ + "atty", + "lazy_static", + "winapi", ] [[package]] @@ -379,12 +347,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b1b9d958c2b1368a663f05538fc1b5975adce1e19f435acceae987aceeeb369" dependencies = [ "lazy_static", - "nom", + "nom 5.1.2", "rust-ini", "serde 1.0.125", "serde-hjson", "serde_json", - "toml 0.5.8", + "toml", "yaml-rust", ] @@ -400,7 +368,7 @@ dependencies = [ "regex", "terminal_size", "unicode-width", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -409,22 +377,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" -[[package]] -name = "cookie" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5795cda0897252e34380a27baf884c53aa7ad9990329cdad96d4c5d027015d44" -dependencies = [ - "aes-gcm", - "base64 0.12.3", - "hkdf", - "hmac", - "percent-encoding 2.1.0", - "rand 0.7.3", - "sha2", - "time", -] - [[package]] name = "core-foundation" version = "0.9.1" @@ -441,6 +393,41 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" +[[package]] +name = "cpuid-bool" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" + +[[package]] +name = "crc" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" +dependencies = [ + "build_const", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f6cb3c7f5b8e51bc3ebb73a2327ad4abdbd119dc13223f14f961d2f38486756" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.1" @@ -448,18 +435,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" dependencies = [ "autocfg", - "cfg-if 1.0.0", + "cfg-if", "lazy_static", ] [[package]] name = "crypto-mac" -version = "0.7.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +checksum = "4857fd85a0c34b3c3297875b747c1e02e06b6a0ea32dd892d8192b9ce0813ea6" dependencies = [ "generic-array", - "subtle 1.0.0", + "subtle", ] [[package]] @@ -484,78 +471,11 @@ dependencies = [ "memchr", ] -[[package]] -name = "devise" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74e04ba2d03c5fa0d954c061fc8c9c288badadffc272ebb87679a89846de3ed3" -dependencies = [ - "devise_codegen", - "devise_core", -] - -[[package]] -name = "devise_codegen" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "066ceb7928ca93a9bedc6d0e612a8a0424048b0ab1f75971b203d01420c055d7" -dependencies = [ - "devise_core", - "quote 0.6.13", -] - -[[package]] -name = "devise_core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf41c59b22b5e3ec0ea55c7847e5f358d340f3a8d6d53a5cf4f1564967f96487" -dependencies = [ - "bitflags", - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.44", -] - -[[package]] -name = "diesel" -version = "1.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "047bfc4d5c3bd2ef6ca6f981941046113524b9a9f9a7cbdfdd7ff40f58e6f542" -dependencies = [ - "bitflags", - "byteorder", - "chrono", - "diesel_derives", - "pq-sys", - "r2d2", -] - -[[package]] -name = "diesel_derives" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" -dependencies = [ - "proc-macro2 1.0.26", - "quote 1.0.9", - "syn 1.0.69", -] - -[[package]] -name = "diesel_migrations" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf3cde8413353dc7f5d72fa8ce0b99a560a359d2c5ef1e5817ca731cd9008f4c" -dependencies = [ - "migrations_internals", - "migrations_macros", -] - [[package]] name = "digest" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ "generic-array", ] @@ -569,13 +489,22 @@ dependencies = [ "dirs-sys", ] +[[package]] +name = "dirs" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142995ed02755914747cc6ca76fc7e4583cd18578746716d0508ea6ed558b9ff" +dependencies = [ + "dirs-sys", +] + [[package]] name = "dirs-next" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "dirs-sys-next", ] @@ -587,7 +516,7 @@ checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a" dependencies = [ "libc", "redox_users 0.3.5", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -598,7 +527,7 @@ checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", "redox_users 0.4.0", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -625,7 +554,7 @@ version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -638,12 +567,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - [[package]] name = "fallible-iterator" version = "0.2.0" @@ -662,19 +585,8 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9a4820f0ccc8a7afd67c39a0f1a0f4b07ca1725164271a64939d7aeb9af065" dependencies = [ - "log 0.4.14", -] - -[[package]] -name = "filetime" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "redox_syscall 0.2.4", - "winapi 0.3.9", + "colored", + "log", ] [[package]] @@ -714,26 +626,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" dependencies = [ "matches", - "percent-encoding 2.1.0", -] - -[[package]] -name = "fsevent" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" -dependencies = [ - "bitflags", - "fsevent-sys", -] - -[[package]] -name = "fsevent-sys" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" -dependencies = [ - "libc", + "percent-encoding", ] [[package]] @@ -743,66 +636,100 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] -name = "fuchsia-zircon" -version = "0.3.3" +name = "funty" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + +[[package]] +name = "futures" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d5813545e459ad3ca1bff9915e9ad7f1a47dc6a91b627ce321d5863b7dd253" dependencies = [ - "bitflags", - "fuchsia-zircon-sys", + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", ] -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - [[package]] name = "futures-channel" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939" +checksum = "ce79c6a52a299137a6013061e0cf0e688fce5d7f1bc60125f520912fdb29ec25" dependencies = [ "futures-core", + "futures-sink", ] [[package]] name = "futures-core" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94" +checksum = "098cd1c6dda6ca01650f1a37a794245eb73181d0d4d4e955e2f3c37db7af1815" + +[[package]] +name = "futures-executor" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f6cb7042eda00f0049b1d2080aa4b93442997ee507eb3828e8bd7577f94c9d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] [[package]] name = "futures-io" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59" +checksum = "365a1a1fb30ea1c03a830fdb2158f5236833ac81fa0ad12fe35b29cddc35cb04" + +[[package]] +name = "futures-macro" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668c6733a182cd7deb4f1de7ba3bf2120823835b3bcfbeacf7d2c4a773c1bb8b" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] [[package]] name = "futures-sink" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3" +checksum = "5c5629433c555de3d82861a7a4e3794a4c40040390907cfbfd7143a92a426c23" [[package]] name = "futures-task" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80" +checksum = "ba7aa51095076f3ba6d9a1f702f74bd05ec65f555d70d2033d55ba8d69f581bc" [[package]] name = "futures-util" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1" +checksum = "3c144ad54d60f23927f0a6b6d816e4271278b64f005ad65e4e35291d2de9c025" dependencies = [ + "futures-channel", "futures-core", "futures-io", + "futures-macro", + "futures-sink", "futures-task", "memchr", "pin-project-lite", "pin-utils", + "proc-macro-hack", + "proc-macro-nested", "slab", ] @@ -814,11 +741,12 @@ checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" [[package]] name = "generic-array" -version = "0.12.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" dependencies = [ "typenum", + "version_check", ] [[package]] @@ -827,7 +755,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] @@ -838,32 +766,17 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "wasi 0.10.2+wasi-snapshot-preview1", ] -[[package]] -name = "ghash" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f0930ed19a7184089ea46d2fedead2f6dc2b674c5db4276b7da336c7cd83252" -dependencies = [ - "polyval", -] - [[package]] name = "gimli" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" -[[package]] -name = "glob" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" - [[package]] name = "h2" version = "0.3.2" @@ -889,7 +802,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" dependencies = [ - "ahash", + "ahash 0.4.7", ] [[package]] @@ -901,6 +814,31 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "headers" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0b7591fb62902706ae8e7aaff416b1b0fa2c0fd0878b46dc13baa3712d8a855" +dependencies = [ + "base64", + "bitflags", + "bytes", + "headers-core", + "http", + "mime", + "sha-1", + "time", +] + +[[package]] +name = "headers-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +dependencies = [ + "http", +] + [[package]] name = "heck" version = "0.3.2" @@ -920,20 +858,16 @@ dependencies = [ ] [[package]] -name = "hkdf" -version = "0.8.0" +name = "hex" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fa08a006102488bd9cd5b8013aabe84955cf5ae22e304c2caf655b633aefae3" -dependencies = [ - "digest", - "hmac", -] +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hmac" -version = "0.7.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" +checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" dependencies = [ "crypto-mac", "digest", @@ -984,28 +918,15 @@ dependencies = [ "serde 1.0.125", "serde_derive", "termcolor", - "toml 0.5.8", + "toml", "uuid", ] [[package]] -name = "hyper" -version = "0.10.16" +name = "humantime" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" -dependencies = [ - "base64 0.9.3", - "httparse", - "language-tags", - "log 0.3.9", - "mime 0.2.6", - "num_cpus", - "time", - "traitobject", - "typeable", - "unicase", - "url 1.7.2", -] +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" @@ -1038,23 +959,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper 0.14.5", + "hyper", "native-tls", "tokio", "tokio-native-tls", ] -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "idna" version = "0.2.2" @@ -1095,23 +1005,12 @@ dependencies = [ ] [[package]] -name = "inotify" -version = "0.7.1" +name = "input_buffer" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f" +checksum = "f97967975f448f1a7ddb12b0bc41069d09ed6a1c161a92687e057325db35d413" dependencies = [ - "bitflags", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", + "bytes", ] [[package]] @@ -1120,16 +1019,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", + "cfg-if", ] [[package]] @@ -1162,34 +1052,12 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" - [[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 = "lexical-core" version = "0.7.5" @@ -1198,7 +1066,7 @@ checksum = "21f866863575d0e1d654fbeeabdc927292fdf862873dc3c96c6f753357e13374" dependencies = [ "arrayvec", "bitflags", - "cfg-if 1.0.0", + "cfg-if", "ryu", "static_assertions", ] @@ -1246,72 +1114,60 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -dependencies = [ - "log 0.4.14", -] - [[package]] name = "log" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + [[package]] name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +[[package]] +name = "md-5" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" +dependencies = [ + "block-buffer", + "digest", + "opaque-debug", +] + [[package]] name = "memchr" version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" -[[package]] -name = "migrations_internals" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b4fc84e4af020b837029e017966f86a1c2d5e83e64b589963d5047525995860" -dependencies = [ - "diesel", -] - -[[package]] -name = "migrations_macros" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c" -dependencies = [ - "migrations_internals", - "proc-macro2 1.0.26", - "quote 1.0.9", - "syn 1.0.69", -] - -[[package]] -name = "mime" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -dependencies = [ - "log 0.3.9", -] - [[package]] name = "mime" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "mime_guess" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "miniz_oxide" version = "0.4.4" @@ -1322,25 +1178,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "mio" -version = "0.6.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" -dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log 0.4.14", - "miow 0.2.2", - "net2", - "slab", - "winapi 0.2.8", -] - [[package]] name = "mio" version = "0.7.11" @@ -1348,34 +1185,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956" dependencies = [ "libc", - "log 0.4.14", - "miow 0.3.7", + "log", + "miow", "ntapi", - "winapi 0.3.9", -] - -[[package]] -name = "mio-extras" -version = "2.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" -dependencies = [ - "lazycell", - "log 0.4.14", - "mio 0.6.23", - "slab", -] - -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", + "winapi", ] [[package]] @@ -1384,7 +1197,25 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" dependencies = [ - "winapi 0.3.9", + "winapi", +] + +[[package]] +name = "multipart" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050aeedc89243f5347c3e237e3e13dc76fbe4ae3742a57b94dc14f69acf76d4" +dependencies = [ + "buf_redux", + "httparse", + "log", + "mime", + "mime_guess", + "quick-error", + "rand 0.7.3", + "safemem", + "tempfile", + "twoway", ] [[package]] @@ -1395,7 +1226,7 @@ checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4" dependencies = [ "lazy_static", "libc", - "log 0.4.14", + "log", "openssl", "openssl-probe", "openssl-sys", @@ -1405,17 +1236,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "net2" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", -] - [[package]] name = "nom" version = "5.1.2" @@ -1424,25 +1244,20 @@ checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" dependencies = [ "lexical-core", "memchr", - "version_check 0.9.2", + "version_check", ] [[package]] -name = "notify" -version = "4.0.15" +name = "nom" +version = "6.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80ae4a7688d1fab81c5bf19c64fc8db920be8d519ce6336ed4e7efe024724dbd" +checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2" dependencies = [ - "bitflags", - "filetime", - "fsevent", - "fsevent-sys", - "inotify", - "libc", - "mio 0.6.23", - "mio-extras", - "walkdir", - "winapi 0.3.9", + "bitvec", + "funty", + "lexical-core", + "memchr", + "version_check", ] [[package]] @@ -1451,7 +1266,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1576,9 +1391,9 @@ checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" [[package]] name = "opaque-debug" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" @@ -1587,7 +1402,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a61075b62a23fef5a29815de7536d940aa35ce96d18ce0cc5076272db678a577" dependencies = [ "bitflags", - "cfg-if 1.0.0", + "cfg-if", "foreign-types", "libc", "once_cell", @@ -1639,12 +1454,12 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "instant", "libc", "redox_syscall 0.2.4", "smallvec", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1658,34 +1473,6 @@ dependencies = [ "regex", ] -[[package]] -name = "pear" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5320f212db967792b67cfe12bd469d08afd6318a249bd917d5c19bc92200ab8a" -dependencies = [ - "pear_codegen", -] - -[[package]] -name = "pear_codegen" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfc1c836fdc3d1ef87c348b237b5b5c4dff922156fb2d968f57734f9669768ca" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.44", - "version_check 0.9.2", - "yansi", -] - -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" - [[package]] name = "percent-encoding" version = "2.1.0" @@ -1707,9 +1494,9 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a490329918e856ed1b083f244e3bfe2d8c4f336407e4ea9e1a9f479ff09049e5" dependencies = [ - "proc-macro2 1.0.26", - "quote 1.0.9", - "syn 1.0.69", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1730,31 +1517,12 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" -[[package]] -name = "polyval" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ec3341498978de3bfd12d1b22f1af1de22818f5473a11e8a6ef997989e3a212" -dependencies = [ - "cfg-if 0.1.10", - "universal-hash", -] - [[package]] name = "ppv-lite86" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" -[[package]] -name = "pq-sys" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac25eee5a0582f45a67e837e350d784e7003bd29a5f460796772061ca49ffda" -dependencies = [ - "vcpkg", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -1762,10 +1530,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.26", - "quote 1.0.9", - "syn 1.0.69", - "version_check 0.9.2", + "proc-macro2", + "quote", + "syn", + "version_check", ] [[package]] @@ -1774,19 +1542,22 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.26", - "quote 1.0.9", - "version_check 0.9.2", + "proc-macro2", + "quote", + "version_check", ] [[package]] -name = "proc-macro2" -version = "0.4.30" +name = "proc-macro-hack" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -dependencies = [ - "unicode-xid 0.1.0", -] +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + +[[package]] +name = "proc-macro-nested" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" @@ -1794,17 +1565,14 @@ version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" dependencies = [ - "unicode-xid 0.2.1", + "unicode-xid", ] [[package]] -name = "quote" -version = "0.6.13" +name = "quick-error" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -dependencies = [ - "proc-macro2 0.4.30", -] +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" @@ -1812,19 +1580,14 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ - "proc-macro2 1.0.26", + "proc-macro2", ] [[package]] -name = "r2d2" -version = "0.8.9" +name = "radium" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545c5bc2b880973c9c10e4067418407a0ccaa3091781d1671d46eb35107cb26f" -dependencies = [ - "log 0.4.14", - "parking_lot", - "scheduled-thread-pool", -] +checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" [[package]] name = "rand" @@ -1846,7 +1609,7 @@ dependencies = [ "libc", "rand_core 0.3.1", "rdrand", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2032,7 +1795,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2041,29 +1804,29 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2296f2fac53979e8ccbc4a1136b25dcefd37be9ed7e4a1f6b05a6029c84ff124" dependencies = [ - "base64 0.13.0", + "base64", "bytes", "encoding_rs", "futures-core", "futures-util", "http", "http-body", - "hyper 0.14.5", + "hyper", "hyper-tls", "ipnet", "js-sys", "lazy_static", - "log 0.4.14", - "mime 0.3.16", + "log", + "mime", "native-tls", - "percent-encoding 2.1.0", + "percent-encoding", "pin-project-lite", "serde 1.0.125", "serde_json", "serde_urlencoded", "tokio", "tokio-native-tls", - "url 2.2.1", + "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -2091,87 +1854,6 @@ dependencies = [ "serde 1.0.125", ] -[[package]] -name = "rocket" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7febfdfd4d43facfc7daba20349ebe2c310c6735bd6a2a9255ea8bc425b4cb13" -dependencies = [ - "atty", - "base64 0.12.3", - "log 0.4.14", - "memchr", - "num_cpus", - "pear", - "rocket_codegen", - "rocket_http", - "state", - "time", - "toml 0.4.10", - "version_check 0.9.2", - "yansi", -] - -[[package]] -name = "rocket_codegen" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceac2c55b2c8b1cdc53add64332defa5fc227f64263b86b4114d1386286d42a3" -dependencies = [ - "devise", - "glob", - "indexmap", - "quote 0.6.13", - "rocket_http", - "version_check 0.9.2", - "yansi", -] - -[[package]] -name = "rocket_contrib" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7954a707f9ca18aa74ca8c1f5d1f900f52a4dceb68e96e3112143f759cfd20e" -dependencies = [ - "diesel", - "log 0.4.14", - "notify", - "r2d2", - "rocket", - "rocket_contrib_codegen", - "serde 1.0.125", - "serde_json", -] - -[[package]] -name = "rocket_contrib_codegen" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30deb6dec53b91fac3538a2a3935cf13e0f462745f9f33bf27bedffbe7265b5d" -dependencies = [ - "devise", - "quote 0.6.13", - "version_check 0.9.2", - "yansi", -] - -[[package]] -name = "rocket_http" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce364100ed7a1bf39257b69ebd014c1d5b4979b0d365d8c9ab0aa9c79645493d" -dependencies = [ - "cookie", - "hyper 0.10.16", - "indexmap", - "pear", - "percent-encoding 1.0.1", - "smallvec", - "state", - "time", - "unicode-xid 0.1.0", -] - [[package]] name = "rusqlite" version = "0.25.0" @@ -2193,7 +1875,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" dependencies = [ - "base64 0.13.0", + "base64", "blake2b_simd", "constant_time_eq", "crossbeam-utils", @@ -2242,15 +1924,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - [[package]] name = "scanlex" version = "0.1.4" @@ -2264,17 +1937,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" dependencies = [ "lazy_static", - "winapi 0.3.9", + "winapi", ] [[package]] -name = "scheduled-thread-pool" -version = "0.2.5" +name = "scoped-tls" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6f74fd1204073fa02d5d5d68bec8021be4c38690b61264b2fdb48083d0e7d7" -dependencies = [ - "parking_lot", -] +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" [[package]] name = "scopeguard" @@ -2316,6 +1986,9 @@ name = "serde" version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" +dependencies = [ + "serde_derive", +] [[package]] name = "serde-hjson" @@ -2335,9 +2008,9 @@ version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" dependencies = [ - "proc-macro2 1.0.26", - "quote 1.0.9", - "syn 1.0.69", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -2364,14 +2037,28 @@ dependencies = [ ] [[package]] -name = "sha2" -version = "0.8.2" +name = "sha-1" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +checksum = "dfebf75d25bd900fd1e7d11501efab59bc846dbc76196839663e6637bba9f25f" dependencies = [ "block-buffer", + "cfg-if", + "cpuid-bool", + "digest", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de" +dependencies = [ + "block-buffer", + "cfg-if", + "cpuid-bool", "digest", - "fake-simd", "opaque-debug", ] @@ -2384,6 +2071,15 @@ dependencies = [ "dirs-next", ] +[[package]] +name = "signal-hook-registry" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" +dependencies = [ + "libc", +] + [[package]] name = "slab" version = "0.4.2" @@ -2403,7 +2099,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2418,10 +2114,107 @@ dependencies = [ ] [[package]] -name = "state" -version = "0.4.2" +name = "sqlformat" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483" +checksum = "6d86e3c77ff882a828346ba401a7ef4b8e440df804491c6064fe8295765de71c" +dependencies = [ + "lazy_static", + "maplit", + "nom 6.1.2", + "regex", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d582b9bc04ec6c03084196efc42c2226b018e9941f03ee62bd88921d500917c0" +dependencies = [ + "sqlx-core", + "sqlx-macros", +] + +[[package]] +name = "sqlx-core" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de52d1d473cebb2abb79c886ef6a8023e965e34c0676a99cfeac2cc7f0fde4c1" +dependencies = [ + "ahash 0.7.2", + "atoi", + "base64", + "bitflags", + "byteorder", + "bytes", + "chrono", + "crc", + "crossbeam-channel", + "crossbeam-queue", + "crossbeam-utils", + "dirs", + "either", + "futures-channel", + "futures-core", + "futures-util", + "hashlink", + "hex", + "hmac", + "itoa", + "libc", + "log", + "md-5", + "memchr", + "once_cell", + "parking_lot", + "percent-encoding", + "rand 0.8.3", + "serde 1.0.125", + "serde_json", + "sha-1", + "sha2", + "smallvec", + "sqlformat", + "sqlx-rt", + "stringprep", + "thiserror", + "tokio-stream", + "url", + "uuid", + "whoami", +] + +[[package]] +name = "sqlx-macros" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a40f0be97e704d3fbf059e7e3333c3735639146a72d586c5534c70e79da88a4" +dependencies = [ + "dotenv", + "either", + "futures", + "heck", + "proc-macro2", + "quote", + "sha2", + "sqlx-core", + "sqlx-rt", + "syn", + "url", +] + +[[package]] +name = "sqlx-rt" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6ae97ab05063ed515cdc23d90253213aa24dda0a288c5ec079af3d10f9771bc" +dependencies = [ + "native-tls", + "once_cell", + "tokio", + "tokio-native-tls", +] [[package]] name = "static_assertions" @@ -2429,6 +2222,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "stringprep" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "strsim" version = "0.8.0" @@ -2454,57 +2257,46 @@ checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.26", - "quote 1.0.9", - "syn 1.0.69", + "proc-macro2", + "quote", + "syn", ] -[[package]] -name = "subtle" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" - [[package]] name = "subtle" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" -[[package]] -name = "syn" -version = "0.15.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "unicode-xid 0.1.0", -] - [[package]] name = "syn" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb" dependencies = [ - "proc-macro2 1.0.26", - "quote 1.0.9", - "unicode-xid 0.2.1", + "proc-macro2", + "quote", + "unicode-xid", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tempfile" version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "rand 0.8.3", "redox_syscall 0.2.4", "remove_dir_all", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2523,7 +2315,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86ca8ced750734db02076f44132d802af0b33b09942331f4459dde8636fd2406" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2547,6 +2339,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.3" @@ -2563,7 +2375,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2591,9 +2403,25 @@ dependencies = [ "bytes", "libc", "memchr", - "mio 0.7.11", + "mio", "num_cpus", + "once_cell", + "parking_lot", "pin-project-lite", + "signal-hook-registry", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -2606,6 +2434,30 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e177a5d8c3bf36de9ebe6d58537d8879e964332f93fb3339e43f618c81361af0" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1a5f475f1b9d077ea1017ecbc60890fda8e54942d680ca0b1d2b47cfa2d861b" +dependencies = [ + "futures-util", + "log", + "pin-project", + "tokio", + "tungstenite", +] + [[package]] name = "tokio-util" version = "0.6.5" @@ -2615,20 +2467,11 @@ dependencies = [ "bytes", "futures-core", "futures-sink", - "log 0.4.14", + "log", "pin-project-lite", "tokio", ] -[[package]] -name = "toml" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" -dependencies = [ - "serde 1.0.125", -] - [[package]] name = "toml" version = "0.5.8" @@ -2650,7 +2493,8 @@ version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", + "log", "pin-project-lite", "tracing-core", ] @@ -2664,12 +2508,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "traitobject" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" - [[package]] name = "try-lock" version = "0.2.3" @@ -2690,10 +2528,32 @@ dependencies = [ ] [[package]] -name = "typeable" -version = "0.1.2" +name = "tungstenite" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" +checksum = "8ada8297e8d70872fa9a551d93250a9f407beb9f37ef86494eb20012a2ff7c24" +dependencies = [ + "base64", + "byteorder", + "bytes", + "http", + "httparse", + "input_buffer", + "log", + "rand 0.8.3", + "sha-1", + "url", + "utf-8", +] + +[[package]] +name = "twoway" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" +dependencies = [ + "memchr", +] [[package]] name = "typenum" @@ -2703,11 +2563,11 @@ checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "unicase" -version = "1.4.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" dependencies = [ - "version_check 0.1.5", + "version_check", ] [[package]] @@ -2740,12 +2600,6 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" - [[package]] name = "unicode-xid" version = "0.2.1" @@ -2753,25 +2607,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] -name = "universal-hash" -version = "0.3.0" +name = "unicode_categories" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0c900f2f9b4116803415878ff48b63da9edb268668e08cf9292d7503114a01" -dependencies = [ - "generic-array", - "subtle 2.4.0", -] - -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -dependencies = [ - "idna 0.1.5", - "matches", - "percent-encoding 1.0.1", -] +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "url" @@ -2780,11 +2619,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" dependencies = [ "form_urlencoded", - "idna 0.2.2", + "idna", "matches", - "percent-encoding 2.1.0", + "percent-encoding", ] +[[package]] +name = "urlencoding" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9232eb53352b4442e40d7900465dfc534e8cb2dc8f18656fcb2ac16112b5593" + +[[package]] +name = "utf-8" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" + [[package]] name = "uuid" version = "0.8.2" @@ -2806,39 +2657,51 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" - [[package]] name = "version_check" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" -[[package]] -name = "walkdir" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" -dependencies = [ - "same-file", - "winapi 0.3.9", - "winapi-util", -] - [[package]] name = "want" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ - "log 0.4.14", + "log", "try-lock", ] +[[package]] +name = "warp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "332d47745e9a0c38636dbd454729b147d16bd1ed08ae67b3ab281c4506771054" +dependencies = [ + "bytes", + "futures", + "headers", + "http", + "hyper", + "log", + "mime", + "mime_guess", + "multipart", + "percent-encoding", + "pin-project", + "scoped-tls", + "serde 1.0.125", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-stream", + "tokio-tungstenite", + "tokio-util", + "tower-service", + "tracing", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -2857,7 +2720,7 @@ version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "serde 1.0.125", "serde_json", "wasm-bindgen-macro", @@ -2871,10 +2734,10 @@ checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae" dependencies = [ "bumpalo", "lazy_static", - "log 0.4.14", - "proc-macro2 1.0.26", - "quote 1.0.9", - "syn 1.0.69", + "log", + "proc-macro2", + "quote", + "syn", "wasm-bindgen-shared", ] @@ -2884,7 +2747,7 @@ version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81b8b767af23de6ac18bf2168b690bed2902743ddf0fb39252e36f9e2bfc63ea" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -2896,7 +2759,7 @@ version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f" dependencies = [ - "quote 1.0.9", + "quote", "wasm-bindgen-macro-support", ] @@ -2906,9 +2769,9 @@ version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c" dependencies = [ - "proc-macro2 1.0.26", - "quote 1.0.9", - "syn 1.0.69", + "proc-macro2", + "quote", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2939,12 +2802,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.9" @@ -2955,12 +2812,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -2973,7 +2824,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2988,18 +2839,14 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] -name = "ws2_32-sys" -version = "0.2.1" +name = "wyz" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" [[package]] name = "yaml-rust" @@ -3009,15 +2856,3 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] - -[[package]] -name = "yansi" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc79f4a1e39857fc00c3f662cbf2651c771f00e9c15fe2abc341806bd46bd71" - -[[package]] -name = "zeroize" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a974bcdd357f0dca4d41677db03436324d45a4c9ed2d0b873a5a360ce41c36" diff --git a/Cargo.toml b/Cargo.toml index 66955c7..9a57f94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ description = "atuin - magical shell history" [dependencies] log = "0.4" -fern = "0.6.0" +fern = {version = "0.6.0", features = ["colored"] } chrono = { version = "0.4", features = ["serde"] } eyre = "0.6" shellexpand = "2" @@ -17,7 +17,6 @@ directories = "3" uuid = { version = "0.8", features = ["v4"] } indicatif = "0.15.0" whoami = "1.1.2" -rocket = "0.4.7" chrono-english = "0.1.4" cli-table = "0.4" config = "0.11" @@ -29,8 +28,6 @@ tui = "0.14" termion = "1.5" unicode-width = "0.1" itertools = "0.10.0" -diesel = { version = "1.4.4", features = ["postgres", "chrono"] } -diesel_migrations = "1.4.0" dotenv = "0.15.0" sodiumoxide = "0.2.6" reqwest = { version = "0.11", features = ["blocking", "json"] } @@ -40,12 +37,13 @@ parse_duration = "2.1.1" rand = "0.8.3" rust-crypto = "^0.2" human-panic = "1.0.3" +tokio = { version = "1", features = ["full"] } +warp = "0.3" +sqlx = { version = "0.5", features = [ "runtime-tokio-native-tls", "uuid", "chrono", "postgres" ] } +async-trait = "0.1.49" +urlencoding = "1.1.1" +humantime = "2.1.0" [dependencies.rusqlite] version = "0.25" features = ["bundled"] - -[dependencies.rocket_contrib] -version = "0.4.7" -default-features = false -features = ["diesel_postgres_pool", "json"] diff --git a/Dockerfile b/Dockerfile index 774468e..0c19ef6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,4 @@ -FROM rust as builder - -RUN rustup default nightly - +FROM rust:1.51-buster as builder RUN cargo new --bin atuin WORKDIR /atuin diff --git a/config.toml b/config.toml index 9d5452c..fe776d6 100644 --- a/config.toml +++ b/config.toml @@ -29,7 +29,7 @@ # sync_address = "https://api.atuin.sh" # This section configures the sync server, if you decide to host your own -[remote] +[server] ## host to bind, can also be passed via CLI args # host = "127.0.0.1" diff --git a/src/api.rs b/src/api.rs index 9097740..82ee660 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,8 +1,9 @@ use chrono::Utc; -// This is shared between the client and the server, and has the data structures -// representing the requests/responses for each method. -// TODO: Properly define responses rather than using json! +#[derive(Debug, Serialize, Deserialize)] +pub struct UserResponse { + pub username: String, +} #[derive(Debug, Serialize, Deserialize)] pub struct RegisterRequest { @@ -11,12 +12,22 @@ pub struct RegisterRequest { pub password: String, } +#[derive(Debug, Serialize, Deserialize)] +pub struct RegisterResponse { + pub session: String, +} + #[derive(Debug, Serialize, Deserialize)] pub struct LoginRequest { pub username: String, pub password: String, } +#[derive(Debug, Serialize, Deserialize)] +pub struct LoginResponse { + pub session: String, +} + #[derive(Debug, Serialize, Deserialize)] pub struct AddHistoryRequest { pub id: String, @@ -31,6 +42,29 @@ pub struct CountResponse { } #[derive(Debug, Serialize, Deserialize)] -pub struct ListHistoryResponse { +pub struct SyncHistoryRequest { + pub sync_ts: chrono::DateTime, + pub history_ts: chrono::DateTime, + pub host: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct SyncHistoryResponse { pub history: Vec, } + +#[derive(Debug, Serialize, Deserialize)] +pub struct ErrorResponse { + pub reason: String, +} + +impl ErrorResponse { + pub fn reply(reason: &str, status: warp::http::StatusCode) -> impl warp::Reply { + warp::reply::with_status( + warp::reply::json(&ErrorResponse { + reason: String::from(reason), + }), + status, + ) + } +} diff --git a/src/command/history.rs b/src/command/history.rs index 3b4a717..627efae 100644 --- a/src/command/history.rs +++ b/src/command/history.rs @@ -53,7 +53,7 @@ fn print_list(h: &[History]) { } impl Cmd { - pub fn run(&self, settings: &Settings, db: &mut impl Database) -> Result<()> { + pub async fn run(&self, settings: &Settings, db: &mut (impl Database + Send)) -> Result<()> { match self { Self::Start { command: words } => { let command = words.join(" "); @@ -69,6 +69,10 @@ impl Cmd { } Self::End { id, exit } => { + if id.trim() == "" { + return Ok(()); + } + let mut h = db.load(id)?; h.exit = *exit; h.duration = chrono::Utc::now().timestamp_nanos() - h.timestamp.timestamp_nanos(); @@ -82,7 +86,7 @@ impl Cmd { } Ok(Fork::Child) => { debug!("running periodic background sync"); - sync::sync(settings, false, db)?; + sync::sync(settings, false, db).await?; } Err(_) => println!("Fork failed"), } diff --git a/src/command/login.rs b/src/command/login.rs index 4f58b77..636ac0d 100644 --- a/src/command/login.rs +++ b/src/command/login.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use std::fs::File; use std::io::prelude::*; -use eyre::Result; +use eyre::{eyre, Result}; use structopt::StructOpt; use crate::settings::Settings; @@ -28,8 +28,13 @@ impl Cmd { let url = format!("{}/login", settings.local.sync_address); let client = reqwest::blocking::Client::new(); + let resp = client.post(url).json(&map).send()?; + if resp.status() != reqwest::StatusCode::OK { + return Err(eyre!("invalid login details")); + } + let session = resp.json::>()?; let session = session["session"].clone(); diff --git a/src/command/mod.rs b/src/command/mod.rs index eeb11a8..cd857e9 100644 --- a/src/command/mod.rs +++ b/src/command/mod.rs @@ -63,16 +63,16 @@ pub fn uuid_v4() -> String { } impl AtuinCmd { - pub fn run(self, db: &mut impl Database, settings: &Settings) -> Result<()> { + pub async fn run(self, db: &mut T, settings: &Settings) -> Result<()> { match self { - Self::History(history) => history.run(settings, db), + Self::History(history) => history.run(settings, db).await, Self::Import(import) => import.run(db), - Self::Server(server) => server.run(settings), + Self::Server(server) => server.run(settings).await, Self::Stats(stats) => stats.run(db, settings), Self::Init => init::init(), Self::Search { query } => search::run(&query, db), - Self::Sync { force } => sync::run(settings, force, db), + Self::Sync { force } => sync::run(settings, force, db).await, Self::Login(l) => l.run(settings), Self::Register(r) => register::run( settings, diff --git a/src/command/search.rs b/src/command/search.rs index b9f3987..d7b477d 100644 --- a/src/command/search.rs +++ b/src/command/search.rs @@ -1,6 +1,8 @@ use eyre::Result; use itertools::Itertools; use std::io::stdout; +use std::time::Duration; + use termion::{event::Key, input::MouseTerminal, raw::IntoRawMode, screen::AlternateScreen}; use tui::{ backend::TermionBackend, @@ -26,6 +28,78 @@ struct State { results_state: ListState, } +#[allow(clippy::clippy::cast_sign_loss)] +impl State { + fn durations(&self) -> Vec { + self.results + .iter() + .map(|h| { + let duration = + Duration::from_millis(std::cmp::max(h.duration, 0) as u64 / 1_000_000); + let duration = humantime::format_duration(duration).to_string(); + let duration: Vec<&str> = duration.split(' ').collect(); + + duration[0].to_string() + }) + .collect() + } + + fn render_results( + &mut self, + f: &mut tui::Frame, + r: tui::layout::Rect, + ) { + let durations = self.durations(); + let max_length = durations + .iter() + .fold(0, |largest, i| std::cmp::max(largest, i.len())); + + let results: Vec = self + .results + .iter() + .enumerate() + .map(|(i, m)| { + let command = m.command.to_string().replace("\n", " ").replace("\t", " "); + + let mut command = Span::raw(command); + + let mut duration = durations[i].clone(); + + while duration.len() < max_length { + duration.push(' '); + } + + let duration = Span::styled( + duration, + Style::default().fg(if m.exit == 0 || m.duration == -1 { + Color::Green + } else { + Color::Red + }), + ); + + if let Some(selected) = self.results_state.selected() { + if selected == i { + command.style = + Style::default().fg(Color::Red).add_modifier(Modifier::BOLD); + } + } + + let spans = Spans::from(vec![duration, Span::raw(" "), command]); + + ListItem::new(spans) + }) + .collect(); + + let results = List::new(results) + .block(Block::default().borders(Borders::ALL).title("History")) + .start_corner(Corner::BottomLeft) + .highlight_symbol(">> "); + + f.render_stateful_widget(results, r, &mut self.results_state); + } +} + fn query_results(app: &mut State, db: &mut impl Database) { let results = match app.input.as_str() { "" => db.list(), @@ -48,7 +122,11 @@ fn key_handler(input: Key, db: &mut impl Database, app: &mut State) -> Option { let i = app.results_state.selected().unwrap_or(0); - return Some(app.results.get(i).unwrap().command.clone()); + return Some( + app.results + .get(i) + .map_or("".to_string(), |h| h.command.clone()), + ); } Key::Char(c) => { app.input.push(c); @@ -163,32 +241,8 @@ fn select_history(query: &[String], db: &mut impl Database) -> Result { let help = Text::from(Spans::from(help)); let help = Paragraph::new(help); - let input = Paragraph::new(app.input.as_ref()) - .block(Block::default().borders(Borders::ALL).title("Search")); - - let results: Vec = app - .results - .iter() - .enumerate() - .map(|(i, m)| { - let mut content = - Span::raw(m.command.to_string().replace("\n", " ").replace("\t", " ")); - - if let Some(selected) = app.results_state.selected() { - if selected == i { - content.style = - Style::default().fg(Color::Red).add_modifier(Modifier::BOLD); - } - } - - ListItem::new(content) - }) - .collect(); - - let results = List::new(results) - .block(Block::default().borders(Borders::ALL).title("History")) - .start_corner(Corner::BottomLeft) - .highlight_symbol(">> "); + let input = Paragraph::new(app.input.clone()) + .block(Block::default().borders(Borders::ALL).title("Query")); let stats = Paragraph::new(Text::from(Span::raw(format!( "history count: {}", @@ -199,8 +253,8 @@ fn select_history(query: &[String], db: &mut impl Database) -> Result { f.render_widget(title, top_left_chunks[0]); f.render_widget(help, top_left_chunks[1]); + app.render_results(f, chunks[1]); f.render_widget(stats, top_right_chunks[0]); - f.render_stateful_widget(results, chunks[1], &mut app.results_state); f.render_widget(input, chunks[2]); f.set_cursor( diff --git a/src/command/server.rs b/src/command/server.rs index bf75794..a783509 100644 --- a/src/command/server.rs +++ b/src/command/server.rs @@ -1,7 +1,7 @@ use eyre::Result; use structopt::StructOpt; -use crate::remote::server; +use crate::server; use crate::settings::Settings; #[derive(StructOpt)] @@ -20,7 +20,7 @@ pub enum Cmd { } impl Cmd { - pub fn run(&self, settings: &Settings) -> Result<()> { + pub async fn run(&self, settings: &Settings) -> Result<()> { match self { Self::Start { host, port } => { let host = host.as_ref().map_or( @@ -29,7 +29,7 @@ impl Cmd { ); let port = port.map_or(settings.server.port, |p| p); - server::launch(settings, host, port) + server::launch(settings, host, port).await } } } diff --git a/src/command/sync.rs b/src/command/sync.rs index facbe57..88217b3 100644 --- a/src/command/sync.rs +++ b/src/command/sync.rs @@ -4,8 +4,8 @@ use crate::local::database::Database; use crate::local::sync; use crate::settings::Settings; -pub fn run(settings: &Settings, force: bool, db: &mut impl Database) -> Result<()> { - sync::sync(settings, force, db)?; +pub async fn run(settings: &Settings, force: bool, db: &mut (impl Database + Send)) -> Result<()> { + sync::sync(settings, force, db).await?; println!( "Sync complete! {} items in database, force: {}", db.history_count()?, diff --git a/src/local/api_client.rs b/src/local/api_client.rs index 434c07b..1b64a29 100644 --- a/src/local/api_client.rs +++ b/src/local/api_client.rs @@ -1,93 +1,94 @@ use chrono::Utc; use eyre::Result; -use reqwest::header::AUTHORIZATION; +use reqwest::header::{HeaderMap, AUTHORIZATION}; +use reqwest::Url; +use sodiumoxide::crypto::secretbox; -use crate::api::{AddHistoryRequest, CountResponse, ListHistoryResponse}; -use crate::local::encryption::{decrypt, load_key}; +use crate::api::{AddHistoryRequest, CountResponse, SyncHistoryResponse}; +use crate::local::encryption::decrypt; use crate::local::history::History; -use crate::settings::Settings; use crate::utils::hash_str; pub struct Client<'a> { - settings: &'a Settings, + sync_addr: &'a str, + token: &'a str, + key: secretbox::Key, + client: reqwest::Client, } impl<'a> Client<'a> { - pub const fn new(settings: &'a Settings) -> Self { - Client { settings } + pub fn new(sync_addr: &'a str, token: &'a str, key: secretbox::Key) -> Self { + Client { + sync_addr, + token, + key, + client: reqwest::Client::new(), + } } - pub fn count(&self) -> Result { - let url = format!("{}/sync/count", self.settings.local.sync_address); - let client = reqwest::blocking::Client::new(); + pub async fn count(&self) -> Result { + let url = format!("{}/sync/count", self.sync_addr); + let url = Url::parse(url.as_str())?; + let token = format!("Token {}", self.token); + let token = token.parse()?; - let resp = client - .get(url) - .header( - AUTHORIZATION, - format!("Token {}", self.settings.local.session_token), - ) - .send()?; + let mut headers = HeaderMap::new(); + headers.insert(AUTHORIZATION, token); - let count = resp.json::()?; + let resp = self.client.get(url).headers(headers).send().await?; + + let count = resp.json::().await?; Ok(count.count) } - pub fn get_history( + pub async fn get_history( &self, sync_ts: chrono::DateTime, history_ts: chrono::DateTime, host: Option, ) -> Result> { - let key = load_key(self.settings)?; - let host = match host { None => hash_str(&format!("{}:{}", whoami::hostname(), whoami::username())), Some(h) => h, }; - // this allows for syncing between users on the same machine let url = format!( "{}/sync/history?sync_ts={}&history_ts={}&host={}", - self.settings.local.sync_address, - sync_ts.to_rfc3339(), - history_ts.to_rfc3339(), + self.sync_addr, + urlencoding::encode(sync_ts.to_rfc3339().as_str()), + urlencoding::encode(history_ts.to_rfc3339().as_str()), host, ); - let client = reqwest::blocking::Client::new(); - let resp = client + let resp = self + .client .get(url) - .header( - AUTHORIZATION, - format!("Token {}", self.settings.local.session_token), - ) - .send()?; + .header(AUTHORIZATION, format!("Token {}", self.token)) + .send() + .await?; - let history = resp.json::()?; + let history = resp.json::().await?; let history = history .history .iter() .map(|h| serde_json::from_str(h).expect("invalid base64")) - .map(|h| decrypt(&h, &key).expect("failed to decrypt history! check your key")) + .map(|h| decrypt(&h, &self.key).expect("failed to decrypt history! check your key")) .collect(); Ok(history) } - pub fn post_history(&self, history: &[AddHistoryRequest]) -> Result<()> { - let client = reqwest::blocking::Client::new(); + pub async fn post_history(&self, history: &[AddHistoryRequest]) -> Result<()> { + let url = format!("{}/history", self.sync_addr); + let url = Url::parse(url.as_str())?; - let url = format!("{}/history", self.settings.local.sync_address); - client + self.client .post(url) .json(history) - .header( - AUTHORIZATION, - format!("Token {}", self.settings.local.session_token), - ) - .send()?; + .header(AUTHORIZATION, format!("Token {}", self.token)) + .send() + .await?; Ok(()) } diff --git a/src/local/database.rs b/src/local/database.rs index 977f11c..abc22bb 100644 --- a/src/local/database.rs +++ b/src/local/database.rs @@ -215,9 +215,9 @@ impl Database for Sqlite { } fn before(&self, timestamp: chrono::DateTime, count: i64) -> Result> { - let mut stmt = self.conn.prepare( - "SELECT * FROM history where timestamp <= ? order by timestamp desc limit ?", - )?; + let mut stmt = self + .conn + .prepare("SELECT * FROM history where timestamp < ? order by timestamp desc limit ?")?; let history_iter = stmt.query_map(params![timestamp.timestamp_nanos(), count], |row| { history_from_sqlite_row(None, row) @@ -236,7 +236,7 @@ impl Database for Sqlite { fn prefix_search(&self, query: &str) -> Result> { self.query( - "select * from history where command like ?1 || '%' order by timestamp asc", + "select * from history where command like ?1 || '%' order by timestamp asc limit 1000", &[query], ) } diff --git a/src/local/import.rs b/src/local/import.rs index d0f679c..3b0b2a6 100644 --- a/src/local/import.rs +++ b/src/local/import.rs @@ -7,6 +7,7 @@ use std::{fs::File, path::Path}; use chrono::prelude::*; use chrono::Utc; use eyre::{eyre, Result}; +use itertools::Itertools; use super::history::History; @@ -42,8 +43,8 @@ impl Zsh { fn parse_extended(line: &str, counter: i64) -> History { let line = line.replacen(": ", "", 2); - let (time, duration) = line.split_once(':').unwrap(); - let (duration, command) = duration.split_once(';').unwrap(); + let (time, duration) = line.splitn(2, ':').collect_tuple().unwrap(); + let (duration, command) = duration.splitn(2, ';').collect_tuple().unwrap(); let time = time .parse::() @@ -60,7 +61,7 @@ fn parse_extended(line: &str, counter: i64) -> History { time, command.trim_end().to_string(), String::from("unknown"), - -1, + 0, // assume 0, we have no way of knowing :( duration, None, None, diff --git a/src/local/sync.rs b/src/local/sync.rs index c22d2f2..e0feb75 100644 --- a/src/local/sync.rs +++ b/src/local/sync.rs @@ -20,12 +20,12 @@ use crate::{api::AddHistoryRequest, utils::hash_str}; // Check if remote has things we don't, and if so, download them. // Returns (num downloaded, total local) -fn sync_download( +async fn sync_download( force: bool, - client: &api_client::Client, - db: &mut impl Database, + client: &api_client::Client<'_>, + db: &mut (impl Database + Send), ) -> Result<(i64, i64)> { - let remote_count = client.count()?; + let remote_count = client.count().await?; let initial_local = db.history_count()?; let mut local_count = initial_local; @@ -41,7 +41,9 @@ fn sync_download( let host = if force { Some(String::from("")) } else { None }; while remote_count > local_count { - let page = client.get_history(last_sync, last_timestamp, host.clone())?; + let page = client + .get_history(last_sync, last_timestamp, host.clone()) + .await?; if page.len() < HISTORY_PAGE_SIZE.try_into().unwrap() { break; @@ -71,13 +73,13 @@ fn sync_download( } // Check if we have things remote doesn't, and if so, upload them -fn sync_upload( +async fn sync_upload( settings: &Settings, _force: bool, - client: &api_client::Client, - db: &mut impl Database, + client: &api_client::Client<'_>, + db: &mut (impl Database + Send), ) -> Result<()> { - let initial_remote_count = client.count()?; + let initial_remote_count = client.count().await?; let mut remote_count = initial_remote_count; let local_count = db.history_count()?; @@ -111,21 +113,25 @@ fn sync_upload( } // anything left over outside of the 100 block size - client.post_history(&buffer)?; + client.post_history(&buffer).await?; cursor = buffer.last().unwrap().timestamp; - remote_count = client.count()?; + remote_count = client.count().await?; } Ok(()) } -pub fn sync(settings: &Settings, force: bool, db: &mut impl Database) -> Result<()> { - let client = api_client::Client::new(settings); +pub async fn sync(settings: &Settings, force: bool, db: &mut (impl Database + Send)) -> Result<()> { + let client = api_client::Client::new( + settings.local.sync_address.as_str(), + settings.local.session_token.as_str(), + load_key(settings)?, + ); - sync_upload(settings, force, &client, db)?; + sync_upload(settings, force, &client, db).await?; - let download = sync_download(force, &client, db)?; + let download = sync_download(force, &client, db).await?; debug!("sync downloaded {}", download.0); diff --git a/src/main.rs b/src/main.rs index 94c7366..0045a94 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,32 +1,19 @@ -#![feature(proc_macro_hygiene)] -#![feature(decl_macro)] #![warn(clippy::pedantic, clippy::nursery)] #![allow(clippy::use_self)] // not 100% reliable use std::path::PathBuf; use eyre::{eyre, Result}; +use fern::colors::{Color, ColoredLevelConfig}; use human_panic::setup_panic; use structopt::{clap::AppSettings, StructOpt}; #[macro_use] extern crate log; -#[macro_use] -extern crate rocket; - #[macro_use] extern crate serde_derive; -#[macro_use] -extern crate diesel; - -#[macro_use] -extern crate diesel_migrations; - -#[macro_use] -extern crate rocket_contrib; - use command::AtuinCmd; use local::database::Sqlite; use settings::Settings; @@ -34,12 +21,10 @@ use settings::Settings; mod api; mod command; mod local; -mod remote; +mod server; mod settings; mod utils; -pub mod schema; - #[derive(StructOpt)] #[structopt( author = "Ellie Huxtable ", @@ -56,7 +41,7 @@ struct Atuin { } impl Atuin { - fn run(self, settings: &Settings) -> Result<()> { + async fn run(self, settings: &Settings) -> Result<()> { let db_path = if let Some(db_path) = self.db { let path = db_path .to_str() @@ -69,26 +54,32 @@ impl Atuin { let mut db = Sqlite::new(db_path)?; - self.atuin.run(&mut db, settings) + self.atuin.run(&mut db, settings).await } } -fn main() -> Result<()> { - setup_panic!(); - let settings = Settings::new()?; +#[tokio::main] +async fn main() -> Result<()> { + let colors = ColoredLevelConfig::new() + .warn(Color::Yellow) + .error(Color::Red); fern::Dispatch::new() - .format(|out, message, record| { + .format(move |out, message, record| { out.finish(format_args!( "{} [{}] {}", - chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), - record.level(), + chrono::Local::now().to_rfc3339(), + colors.color(record.level()), message )) }) .level(log::LevelFilter::Info) + .level_for("sqlx", log::LevelFilter::Warn) .chain(std::io::stdout()) .apply()?; - Atuin::from_args().run(&settings) + let settings = Settings::new()?; + setup_panic!(); + + Atuin::from_args().run(&settings).await } diff --git a/src/remote/database.rs b/src/remote/database.rs deleted file mode 100644 index 03973ca..0000000 --- a/src/remote/database.rs +++ /dev/null @@ -1,22 +0,0 @@ -use diesel::pg::PgConnection; -use diesel::prelude::*; -use eyre::{eyre, Result}; - -use crate::settings::Settings; - -#[database("atuin")] -pub struct AtuinDbConn(diesel::PgConnection); - -// TODO: connection pooling -pub fn establish_connection(settings: &Settings) -> Result { - if settings.server.db_uri == "default_uri" { - Err(eyre!( - "Please configure your database! Set db_uri in config.toml" - )) - } else { - let database_url = &settings.server.db_uri; - let conn = PgConnection::establish(database_url)?; - - Ok(conn) - } -} diff --git a/src/remote/mod.rs b/src/remote/mod.rs deleted file mode 100644 index 7147b88..0000000 --- a/src/remote/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod auth; -pub mod database; -pub mod models; -pub mod server; -pub mod views; diff --git a/src/remote/server.rs b/src/remote/server.rs deleted file mode 100644 index ee481ca..0000000 --- a/src/remote/server.rs +++ /dev/null @@ -1,61 +0,0 @@ -use std::collections::HashMap; - -use crate::remote::database::establish_connection; -use crate::settings::Settings; - -use super::database::AtuinDbConn; - -use eyre::Result; -use rocket::config::{Config, Environment, LoggingLevel, Value}; - -// a bunch of these imports are generated by macros, it's easier to wildcard -#[allow(clippy::clippy::wildcard_imports)] -use super::views::*; - -#[allow(clippy::clippy::wildcard_imports)] -use super::auth::*; - -embed_migrations!("migrations"); - -pub fn launch(settings: &Settings, host: String, port: u16) -> Result<()> { - let settings: Settings = settings.clone(); // clone so rocket can manage it - - let mut database_config = HashMap::new(); - let mut databases = HashMap::new(); - - database_config.insert("url", Value::from(settings.server.db_uri.clone())); - databases.insert("atuin", Value::from(database_config)); - - let connection = establish_connection(&settings)?; - - embedded_migrations::run(&connection).expect("failed to run migrations"); - - let config = Config::build(Environment::Production) - .address(host) - .log_level(LoggingLevel::Normal) - .port(port) - .extra("databases", databases) - .finalize() - .unwrap(); - - let app = rocket::custom(config); - - app.mount( - "/", - routes![ - index, - register, - add_history, - login, - get_user, - sync_count, - sync_list - ], - ) - .manage(settings) - .attach(AtuinDbConn::fairing()) - .register(catchers![internal_error, bad_request]) - .launch(); - - Ok(()) -} diff --git a/src/remote/views.rs b/src/remote/views.rs deleted file mode 100644 index 08dff13..0000000 --- a/src/remote/views.rs +++ /dev/null @@ -1,185 +0,0 @@ -use chrono::Utc; -use rocket::http::uri::Uri; -use rocket::http::RawStr; -use rocket::http::{ContentType, Status}; -use rocket::request::FromFormValue; -use rocket::request::Request; -use rocket::response; -use rocket::response::{Responder, Response}; -use rocket_contrib::databases::diesel; -use rocket_contrib::json::{Json, JsonValue}; - -use self::diesel::prelude::*; - -use crate::api::AddHistoryRequest; -use crate::schema::history; -use crate::settings::HISTORY_PAGE_SIZE; - -use super::database::AtuinDbConn; -use super::models::{History, NewHistory, User}; - -#[derive(Debug)] -pub struct ApiResponse { - pub json: JsonValue, - pub status: Status, -} - -impl<'r> Responder<'r> for ApiResponse { - fn respond_to(self, req: &Request) -> response::Result<'r> { - Response::build_from(self.json.respond_to(req).unwrap()) - .status(self.status) - .header(ContentType::JSON) - .ok() - } -} - -#[get("/")] -pub const fn index() -> &'static str { - "\"Through the fathomless deeps of space swims the star turtle Great A\u{2019}Tuin, bearing on its back the four giant elephants who carry on their shoulders the mass of the Discworld.\"\n\t-- Sir Terry Pratchett" -} - -#[catch(500)] -pub fn internal_error(_req: &Request) -> ApiResponse { - ApiResponse { - status: Status::InternalServerError, - json: json!({"status": "error", "message": "an internal server error has occured"}), - } -} - -#[catch(400)] -pub fn bad_request(_req: &Request) -> ApiResponse { - ApiResponse { - status: Status::InternalServerError, - json: json!({"status": "error", "message": "bad request. don't do that."}), - } -} - -#[post("/history", data = "")] -#[allow( - clippy::clippy::cast_sign_loss, - clippy::cast_possible_truncation, - clippy::clippy::needless_pass_by_value -)] -pub fn add_history( - conn: AtuinDbConn, - user: User, - add_history: Json>, -) -> ApiResponse { - let new_history: Vec = add_history - .iter() - .map(|h| NewHistory { - client_id: h.id.as_str(), - hostname: h.hostname.to_string(), - user_id: user.id, - timestamp: h.timestamp.naive_utc(), - data: h.data.as_str(), - }) - .collect(); - - match diesel::insert_into(history::table) - .values(&new_history) - .on_conflict_do_nothing() - .execute(&*conn) - { - Ok(_) => ApiResponse { - status: Status::Ok, - json: json!({"status": "ok", "message": "history added"}), - }, - Err(_) => ApiResponse { - status: Status::BadRequest, - json: json!({"status": "error", "message": "failed to add history"}), - }, - } -} - -#[get("/sync/count")] -#[allow(clippy::wildcard_imports, clippy::needless_pass_by_value)] -pub fn sync_count(conn: AtuinDbConn, user: User) -> ApiResponse { - use crate::schema::history::dsl::*; - - // we need to return the number of history items we have for this user - // in the future I'd like to use something like a merkel tree to calculate - // which day specifically needs syncing - let count = history - .filter(user_id.eq(user.id)) - .count() - .first::(&*conn); - - if count.is_err() { - error!("failed to count: {}", count.err().unwrap()); - - return ApiResponse { - json: json!({"message": "internal server error"}), - status: Status::InternalServerError, - }; - } - - ApiResponse { - status: Status::Ok, - json: json!({"count": count.ok()}), - } -} - -pub struct UtcDateTime(chrono::DateTime); - -impl<'v> FromFormValue<'v> for UtcDateTime { - type Error = &'v RawStr; - - fn from_form_value(form_value: &'v RawStr) -> Result { - let time = Uri::percent_decode(form_value.as_bytes()).map_err(|_| form_value)?; - let time = time.to_string(); - - match chrono::DateTime::parse_from_rfc3339(time.as_str()) { - Ok(t) => Ok(UtcDateTime(t.with_timezone(&Utc))), - Err(e) => { - error!("failed to parse time {}, got: {}", time, e); - Err(form_value) - } - } - } -} - -// Request a list of all history items added to the DB after a given timestamp. -// Provide the current hostname, so that we don't send the client data that -// originated from them -#[get("/sync/history?&&")] -#[allow(clippy::wildcard_imports, clippy::needless_pass_by_value)] -pub fn sync_list( - conn: AtuinDbConn, - user: User, - sync_ts: UtcDateTime, - history_ts: UtcDateTime, - host: String, -) -> ApiResponse { - use crate::schema::history::dsl::*; - - // we need to return the number of history items we have for this user - // in the future I'd like to use something like a merkel tree to calculate - // which day specifically needs syncing - // TODO: Allow for configuring the page size, both from params, and setting - // the max in config. 100 is fine for now. - let h = history - .filter(user_id.eq(user.id)) - .filter(hostname.ne(host)) - .filter(created_at.ge(sync_ts.0.naive_utc())) - .filter(timestamp.ge(history_ts.0.naive_utc())) - .order(timestamp.asc()) - .limit(HISTORY_PAGE_SIZE) - .load::(&*conn); - - if let Err(e) = h { - error!("failed to load history: {}", e); - - return ApiResponse { - json: json!({"message": "internal server error"}), - status: Status::InternalServerError, - }; - } - - let user_data: Vec = h.unwrap().iter().map(|i| i.data.to_string()).collect(); - - ApiResponse { - status: Status::Ok, - json: json!({ "history": user_data }), - } -} diff --git a/src/schema.rs b/src/schema.rs deleted file mode 100644 index 84bf5ba..0000000 --- a/src/schema.rs +++ /dev/null @@ -1,30 +0,0 @@ -table! { - history (id) { - id -> Int8, - client_id -> Text, - user_id -> Int8, - hostname -> Text, - timestamp -> Timestamp, - data -> Varchar, - created_at -> Timestamp, - } -} - -table! { - sessions (id) { - id -> Int8, - user_id -> Int8, - token -> Varchar, - } -} - -table! { - users (id) { - id -> Int8, - username -> Varchar, - email -> Varchar, - password -> Varchar, - } -} - -allow_tables_to_appear_in_same_query!(history, sessions, users,); diff --git a/src/remote/auth.rs b/src/server/auth.rs similarity index 99% rename from src/remote/auth.rs rename to src/server/auth.rs index cf61b07..52a7310 100644 --- a/src/remote/auth.rs +++ b/src/server/auth.rs @@ -1,3 +1,4 @@ +/* use self::diesel::prelude::*; use eyre::Result; use rocket::http::Status; @@ -218,3 +219,4 @@ pub fn login(conn: AtuinDbConn, login: Json) -> ApiResponse { json: json!({"session": session.token}), } } +*/ diff --git a/src/server/database.rs b/src/server/database.rs new file mode 100644 index 0000000..5945baa --- /dev/null +++ b/src/server/database.rs @@ -0,0 +1,202 @@ +use async_trait::async_trait; + +use eyre::{eyre, Result}; +use sqlx::postgres::PgPoolOptions; + +use crate::settings::HISTORY_PAGE_SIZE; + +use super::models::{History, NewHistory, NewSession, NewUser, Session, User}; + +#[async_trait] +pub trait Database { + async fn get_session(&self, token: &str) -> Result; + async fn get_session_user(&self, token: &str) -> Result; + async fn add_session(&self, session: &NewSession) -> Result<()>; + + async fn get_user(&self, username: String) -> Result; + async fn get_user_session(&self, u: &User) -> Result; + async fn add_user(&self, user: NewUser) -> Result; + + async fn count_history(&self, user: &User) -> Result; + async fn list_history( + &self, + user: &User, + created_since: chrono::NaiveDateTime, + since: chrono::NaiveDateTime, + host: String, + ) -> Result>; + async fn add_history(&self, history: &[NewHistory]) -> Result<()>; +} + +#[derive(Clone)] +pub struct Postgres { + pool: sqlx::Pool, +} + +impl Postgres { + pub async fn new(uri: &str) -> Result { + let pool = PgPoolOptions::new() + .max_connections(100) + .connect(uri) + .await?; + + Ok(Self { pool }) + } +} + +#[async_trait] +impl Database for Postgres { + async fn get_session(&self, token: &str) -> Result { + let res: Option = + sqlx::query_as::<_, Session>("select * from sessions where token = $1") + .bind(token) + .fetch_optional(&self.pool) + .await?; + + if let Some(s) = res { + Ok(s) + } else { + Err(eyre!("could not find session")) + } + } + + async fn get_user(&self, username: String) -> Result { + let res: Option = + sqlx::query_as::<_, User>("select * from users where username = $1") + .bind(username) + .fetch_optional(&self.pool) + .await?; + + if let Some(u) = res { + Ok(u) + } else { + Err(eyre!("could not find user")) + } + } + + async fn get_session_user(&self, token: &str) -> Result { + let res: Option = sqlx::query_as::<_, User>( + "select * from users + inner join sessions + on users.id = sessions.user_id + and sessions.token = $1", + ) + .bind(token) + .fetch_optional(&self.pool) + .await?; + + if let Some(u) = res { + Ok(u) + } else { + Err(eyre!("could not find user")) + } + } + + async fn count_history(&self, user: &User) -> Result { + let res: (i64,) = sqlx::query_as( + "select count(1) from history + where user_id = $1", + ) + .bind(user.id) + .fetch_one(&self.pool) + .await?; + + Ok(res.0) + } + + async fn list_history( + &self, + user: &User, + created_since: chrono::NaiveDateTime, + since: chrono::NaiveDateTime, + host: String, + ) -> Result> { + let res = sqlx::query_as::<_, History>( + "select * from history + where user_id = $1 + and hostname != $2 + and created_at >= $3 + and timestamp >= $4 + order by timestamp asc + limit $5", + ) + .bind(user.id) + .bind(host) + .bind(created_since) + .bind(since) + .bind(HISTORY_PAGE_SIZE) + .fetch_all(&self.pool) + .await?; + + Ok(res) + } + + async fn add_history(&self, history: &[NewHistory]) -> Result<()> { + let mut tx = self.pool.begin().await?; + + for i in history { + sqlx::query( + "insert into history + (client_id, user_id, hostname, timestamp, data) + values ($1, $2, $3, $4, $5) + on conflict do nothing + ", + ) + .bind(i.client_id) + .bind(i.user_id) + .bind(i.hostname) + .bind(i.timestamp) + .bind(i.data) + .execute(&mut tx) + .await?; + } + + tx.commit().await?; + + Ok(()) + } + + async fn add_user(&self, user: NewUser) -> Result { + let res: (i64,) = sqlx::query_as( + "insert into users + (username, email, password) + values($1, $2, $3) + returning id", + ) + .bind(user.username.as_str()) + .bind(user.email.as_str()) + .bind(user.password) + .fetch_one(&self.pool) + .await?; + + Ok(res.0) + } + + async fn add_session(&self, session: &NewSession) -> Result<()> { + sqlx::query( + "insert into sessions + (user_id, token) + values($1, $2)", + ) + .bind(session.user_id) + .bind(session.token) + .execute(&self.pool) + .await?; + + Ok(()) + } + + async fn get_user_session(&self, u: &User) -> Result { + let res: Option = + sqlx::query_as::<_, Session>("select * from sessions where user_id = $1") + .bind(u.id) + .fetch_optional(&self.pool) + .await?; + + if let Some(s) = res { + Ok(s) + } else { + Err(eyre!("could not find session")) + } + } +} diff --git a/src/server/handlers/history.rs b/src/server/handlers/history.rs new file mode 100644 index 0000000..4fd6f03 --- /dev/null +++ b/src/server/handlers/history.rs @@ -0,0 +1,89 @@ +use std::convert::Infallible; + +use warp::{http::StatusCode, reply::json}; + +use crate::api::{ + AddHistoryRequest, CountResponse, ErrorResponse, SyncHistoryRequest, SyncHistoryResponse, +}; +use crate::server::database::Database; +use crate::server::models::{NewHistory, User}; + +pub async fn count( + user: User, + db: impl Database + Clone + Send + Sync, +) -> Result, Infallible> { + db.count_history(&user).await.map_or( + Ok(Box::new(ErrorResponse::reply( + "failed to query history count", + StatusCode::INTERNAL_SERVER_ERROR, + ))), + |count| Ok(Box::new(json(&CountResponse { count }))), + ) +} + +pub async fn list( + req: SyncHistoryRequest, + user: User, + db: impl Database + Clone + Send + Sync, +) -> Result, Infallible> { + let history = db + .list_history( + &user, + req.sync_ts.naive_utc(), + req.history_ts.naive_utc(), + req.host, + ) + .await; + + if let Err(e) = history { + error!("failed to load history: {}", e); + let resp = + ErrorResponse::reply("failed to load history", StatusCode::INTERNAL_SERVER_ERROR); + let resp = Box::new(resp); + return Ok(resp); + } + + let history: Vec = history + .unwrap() + .iter() + .map(|i| i.data.to_string()) + .collect(); + + debug!( + "loaded {} items of history for user {}", + history.len(), + user.id + ); + + Ok(Box::new(json(&SyncHistoryResponse { history }))) +} + +pub async fn add( + req: Vec, + user: User, + db: impl Database + Clone + Send + Sync, +) -> Result, Infallible> { + debug!("request to add {} history items", req.len()); + + let history: Vec = req + .iter() + .map(|h| NewHistory { + client_id: h.id.as_str(), + user_id: user.id, + hostname: h.hostname.as_str(), + timestamp: h.timestamp.naive_utc(), + data: h.data.as_str(), + }) + .collect(); + + if let Err(e) = db.add_history(&history).await { + error!("failed to add history: {}", e); + + return Ok(Box::new(ErrorResponse::reply( + "failed to add history", + StatusCode::INTERNAL_SERVER_ERROR, + ))); + }; + + Ok(Box::new(warp::reply())) +} diff --git a/src/server/handlers/mod.rs b/src/server/handlers/mod.rs new file mode 100644 index 0000000..3c20538 --- /dev/null +++ b/src/server/handlers/mod.rs @@ -0,0 +1,6 @@ +pub mod history; +pub mod user; + +pub const fn index() -> &'static str { + "\"Through the fathomless deeps of space swims the star turtle Great A\u{2019}Tuin, bearing on its back the four giant elephants who carry on their shoulders the mass of the Discworld.\"\n\t-- Sir Terry Pratchett" +} diff --git a/src/server/handlers/user.rs b/src/server/handlers/user.rs new file mode 100644 index 0000000..782d7db --- /dev/null +++ b/src/server/handlers/user.rs @@ -0,0 +1,140 @@ +use std::convert::Infallible; + +use sodiumoxide::crypto::pwhash::argon2id13; +use uuid::Uuid; +use warp::http::StatusCode; +use warp::reply::json; + +use crate::api::{ + ErrorResponse, LoginRequest, LoginResponse, RegisterRequest, RegisterResponse, UserResponse, +}; +use crate::server::database::Database; +use crate::server::models::{NewSession, NewUser}; +use crate::settings::Settings; +use crate::utils::hash_secret; + +pub fn verify_str(secret: &str, verify: &str) -> bool { + sodiumoxide::init().unwrap(); + + let mut padded = [0_u8; 128]; + secret.as_bytes().iter().enumerate().for_each(|(i, val)| { + padded[i] = *val; + }); + + match argon2id13::HashedPassword::from_slice(&padded) { + Some(hp) => argon2id13::pwhash_verify(&hp, verify.as_bytes()), + None => false, + } +} + +pub async fn get( + username: String, + db: impl Database + Clone + Send + Sync, +) -> Result, Infallible> { + let user = match db.get_user(username).await { + Ok(user) => user, + Err(e) => { + debug!("user not found: {}", e); + return Ok(Box::new(ErrorResponse::reply( + "user not found", + StatusCode::NOT_FOUND, + ))); + } + }; + + Ok(Box::new(warp::reply::json(&UserResponse { + username: user.username, + }))) +} + +pub async fn register( + register: RegisterRequest, + settings: Settings, + db: impl Database + Clone + Send + Sync, +) -> Result, Infallible> { + if !settings.server.open_registration { + return Ok(Box::new(ErrorResponse::reply( + "this server is not open for registrations", + StatusCode::BAD_REQUEST, + ))); + } + + let hashed = hash_secret(register.password.as_str()); + + let new_user = NewUser { + email: register.email, + username: register.username, + password: hashed, + }; + + let user_id = match db.add_user(new_user).await { + Ok(id) => id, + Err(e) => { + error!("failed to add user: {}", e); + return Ok(Box::new(ErrorResponse::reply( + "failed to add user", + StatusCode::BAD_REQUEST, + ))); + } + }; + + let token = Uuid::new_v4().to_simple().to_string(); + + let new_session = NewSession { + user_id, + token: token.as_str(), + }; + + match db.add_session(&new_session).await { + Ok(_) => Ok(Box::new(json(&RegisterResponse { session: token }))), + Err(e) => { + error!("failed to add session: {}", e); + Ok(Box::new(ErrorResponse::reply( + "failed to register user", + StatusCode::BAD_REQUEST, + ))) + } + } +} + +pub async fn login( + login: LoginRequest, + db: impl Database + Clone + Send + Sync, +) -> Result, Infallible> { + let user = match db.get_user(login.username.clone()).await { + Ok(u) => u, + Err(e) => { + error!("failed to get user {}: {}", login.username.clone(), e); + + return Ok(Box::new(ErrorResponse::reply( + "user not found", + StatusCode::NOT_FOUND, + ))); + } + }; + + let session = match db.get_user_session(&user).await { + Ok(u) => u, + Err(e) => { + error!("failed to get session for {}: {}", login.username, e); + + return Ok(Box::new(ErrorResponse::reply( + "user not found", + StatusCode::NOT_FOUND, + ))); + } + }; + + let verified = verify_str(user.password.as_str(), login.password.as_str()); + + if !verified { + return Ok(Box::new(ErrorResponse::reply( + "user not found", + StatusCode::NOT_FOUND, + ))); + } + + Ok(Box::new(warp::reply::json(&LoginResponse { + session: session.token, + }))) +} diff --git a/src/server/mod.rs b/src/server/mod.rs new file mode 100644 index 0000000..d5e083d --- /dev/null +++ b/src/server/mod.rs @@ -0,0 +1,23 @@ +use std::net::IpAddr; + +use eyre::Result; + +use crate::settings::Settings; + +pub mod auth; +pub mod database; +pub mod handlers; +pub mod models; +pub mod router; + +pub async fn launch(settings: &Settings, host: String, port: u16) -> Result<()> { + // routes to run: + // index, register, add_history, login, get_user, sync_count, sync_list + let host = host.parse::()?; + + let r = router::router(settings).await?; + + warp::serve(r).run((host, port)).await; + + Ok(()) +} diff --git a/src/remote/models.rs b/src/server/models.rs similarity index 55% rename from src/remote/models.rs rename to src/server/models.rs index 7f6f776..fbf1897 100644 --- a/src/remote/models.rs +++ b/src/server/models.rs @@ -1,10 +1,6 @@ use chrono::prelude::*; -use crate::schema::{history, sessions, users}; - -#[derive(Deserialize, Serialize, Identifiable, Queryable, Associations)] -#[table_name = "history"] -#[belongs_to(User)] +#[derive(sqlx::FromRow)] pub struct History { pub id: i64, pub client_id: String, // a client generated ID @@ -17,7 +13,16 @@ pub struct History { pub created_at: NaiveDateTime, } -#[derive(Identifiable, Queryable, Associations)] +pub struct NewHistory<'a> { + pub client_id: &'a str, + pub user_id: i64, + pub hostname: &'a str, + pub timestamp: chrono::NaiveDateTime, + + pub data: &'a str, +} + +#[derive(sqlx::FromRow)] pub struct User { pub id: i64, pub username: String, @@ -25,35 +30,19 @@ pub struct User { pub password: String, } -#[derive(Queryable, Identifiable, Associations)] -#[belongs_to(User)] +#[derive(sqlx::FromRow)] pub struct Session { pub id: i64, pub user_id: i64, pub token: String, } -#[derive(Insertable)] -#[table_name = "history"] -pub struct NewHistory<'a> { - pub client_id: &'a str, - pub user_id: i64, - pub hostname: String, - pub timestamp: chrono::NaiveDateTime, - - pub data: &'a str, +pub struct NewUser { + pub username: String, + pub email: String, + pub password: String, } -#[derive(Insertable)] -#[table_name = "users"] -pub struct NewUser<'a> { - pub username: &'a str, - pub email: &'a str, - pub password: &'a str, -} - -#[derive(Insertable)] -#[table_name = "sessions"] pub struct NewSession<'a> { pub user_id: i64, pub token: &'a str, diff --git a/src/server/router.rs b/src/server/router.rs new file mode 100644 index 0000000..ed317ab --- /dev/null +++ b/src/server/router.rs @@ -0,0 +1,121 @@ +use std::convert::Infallible; + +use eyre::Result; +use warp::Filter; + +use super::handlers; +use super::{database::Database, database::Postgres}; +use crate::server::models::User; +use crate::{api::SyncHistoryRequest, settings::Settings}; + +fn with_settings( + settings: Settings, +) -> impl Filter + Clone { + warp::any().map(move || settings.clone()) +} + +fn with_db( + db: impl Database + Clone + Send + Sync, +) -> impl Filter + Clone { + warp::any().map(move || db.clone()) +} + +fn with_user( + postgres: Postgres, +) -> impl Filter + Clone { + warp::header::("authorization").and_then(move |header: String| { + // async closures are still buggy :( + let postgres = postgres.clone(); + + async move { + let header: Vec<&str> = header.split(' ').collect(); + + let token; + + if header.len() == 2 { + if header[0] != "Token" { + return Err(warp::reject()); + } + + token = header[1]; + } else { + return Err(warp::reject()); + } + + let user = postgres + .get_session_user(token) + .await + .map_err(|_| warp::reject())?; + + Ok(user) + } + }) +} + +pub async fn router( + settings: &Settings, +) -> Result + Clone> { + let postgres = Postgres::new(settings.server.db_uri.as_str()).await?; + let index = warp::get().and(warp::path::end()).map(handlers::index); + + let count = warp::get() + .and(warp::path("sync")) + .and(warp::path("count")) + .and(warp::path::end()) + .and(with_user(postgres.clone())) + .and(with_db(postgres.clone())) + .and_then(handlers::history::count); + + let sync = warp::get() + .and(warp::path("sync")) + .and(warp::path("history")) + .and(warp::query::()) + .and(warp::path::end()) + .and(with_user(postgres.clone())) + .and(with_db(postgres.clone())) + .and_then(handlers::history::list); + + let add_history = warp::post() + .and(warp::path("history")) + .and(warp::path::end()) + .and(warp::body::json()) + .and(with_user(postgres.clone())) + .and(with_db(postgres.clone())) + .and_then(handlers::history::add); + + let user = warp::get() + .and(warp::path("user")) + .and(warp::path::param::()) + .and(warp::path::end()) + .and(with_db(postgres.clone())) + .and_then(handlers::user::get); + + let register = warp::post() + .and(warp::path("register")) + .and(warp::path::end()) + .and(warp::body::json()) + .and(with_settings(settings.clone())) + .and(with_db(postgres.clone())) + .and_then(handlers::user::register); + + let login = warp::post() + .and(warp::path("login")) + .and(warp::path::end()) + .and(warp::body::json()) + .and(with_db(postgres)) + .and_then(handlers::user::login); + + let r = warp::any() + .and( + index + .or(count) + .or(sync) + .or(add_history) + .or(user) + .or(register) + .or(login), + ) + .with(warp::filters::log::log("atuin::api")); + + Ok(r) +} diff --git a/src/settings.rs b/src/settings.rs index f3bc62e..5325610 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -161,7 +161,7 @@ impl Settings { // Finally, set the auth token if Path::new(session_path.to_string().as_str()).exists() { let token = std::fs::read_to_string(session_path.to_string())?; - s.set("local.session_token", token)?; + s.set("local.session_token", token.trim())?; } else { s.set("local.session_token", "not logged in")?; } diff --git a/src/shell/atuin.zsh b/src/shell/atuin.zsh index d2abf3c..d6d58f5 100644 --- a/src/shell/atuin.zsh +++ b/src/shell/atuin.zsh @@ -16,6 +16,7 @@ _atuin_precmd(){ [[ -z "${ATUIN_HISTORY_ID}" ]] && return atuin history end $ATUIN_HISTORY_ID --exit $EXIT + export ATUIN_HISTORY_ID="" } _atuin_search(){