diff --git a/Cargo.lock b/Cargo.lock index e2c5db569d..a7c0e5b31f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,7 +11,7 @@ dependencies = [ "actix-rt", "actix_derive", "bitflags", - "bytes", + "bytes 1.3.0", "crossbeam-channel", "futures-core", "futures-sink", @@ -20,9 +20,9 @@ dependencies = [ "log", "once_cell", "parking_lot 0.12.1", - "pin-project-lite", + "pin-project-lite 0.2.9", "smallvec", - "tokio", + "tokio 1.22.0", "tokio-util 0.7.4", ] @@ -33,21 +33,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57a7559404a7f3573127aab53c08ce37a6c6a315c374a31070f3c91cd1b4a7fe" dependencies = [ "bitflags", - "bytes", + "bytes 1.3.0", "futures-core", "futures-sink", "log", "memchr", - "pin-project-lite", - "tokio", + "pin-project-lite 0.2.9", + "tokio 1.22.0", "tokio-util 0.7.4", ] [[package]] name = "actix-cors" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "684a6ce1562a5fcca49bc9302896c63547eea78a1e405e837e7416affd8b6eb9" +checksum = "b340e9cfa5b08690aae90fb61beb44e9b06f44fe3d0f93781aaa58cfba86245e" dependencies = [ "actix-utils", "actix-web", @@ -72,7 +72,7 @@ dependencies = [ "base64", "bitflags", "brotli", - "bytes", + "bytes 1.3.0", "bytestring", "derive_more", "encoding_rs", @@ -82,12 +82,12 @@ dependencies = [ "http", "httparse", "httpdate", - "itoa 1.0.3", + "itoa 1.0.4", "language-tags", "local-channel", "mime", "percent-encoding", - "pin-project-lite", + "pin-project-lite 0.2.9", "rand", "sha1", "smallvec", @@ -126,7 +126,7 @@ checksum = "7ea16c295198e958ef31930a6ef37d0fb64e9ca3b6116e6b93a8bdae96ee1000" dependencies = [ "actix-macros", "futures-core", - "tokio", + "tokio 1.22.0", ] [[package]] @@ -143,7 +143,7 @@ dependencies = [ "mio", "num_cpus", "socket2", - "tokio", + "tokio 1.22.0", "tracing 0.1.36", ] @@ -155,7 +155,7 @@ checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" dependencies = [ "futures-core", "paste", - "pin-project-lite", + "pin-project-lite 0.2.9", ] [[package]] @@ -171,7 +171,7 @@ dependencies = [ "futures-core", "http", "log", - "pin-project-lite", + "pin-project-lite 0.2.9", "tokio-rustls 0.23.4", "tokio-util 0.7.4", "webpki-roots", @@ -179,12 +179,12 @@ dependencies = [ [[package]] name = "actix-utils" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e491cbaac2e7fc788dfff99ff48ef317e23b3cf63dbaf7aaab6418f40f92aa94" +checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" dependencies = [ "local-waker", - "pin-project-lite", + "pin-project-lite 0.2.9", ] [[package]] @@ -203,7 +203,7 @@ dependencies = [ "actix-utils", "actix-web-codegen", "ahash", - "bytes", + "bytes 1.3.0", "bytestring", "cfg-if", "cookie", @@ -212,12 +212,12 @@ dependencies = [ "futures-core", "futures-util", "http", - "itoa 1.0.3", + "itoa 1.0.4", "language-tags", "log", "mime", "once_cell", - "pin-project-lite", + "pin-project-lite 0.2.9", "regex", "serde", "serde_json", @@ -270,9 +270,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.19" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] @@ -303,9 +303,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.65" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" [[package]] name = "arc-swap" @@ -315,9 +315,9 @@ checksum = "983cd8b9d4b02a6dc6ffa557262eb5858a27a0038ffffe21a0f133eaa819a164" [[package]] name = "arcstr" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d5ebd6061b8b70d59b36bc58d2337540bd7cc1f23ab2bea356f452bc7fe3505" +checksum = "3f907281554a3d0312bb7aab855a8e0ef6cbf1614d06de54105039ca8b34460e" [[package]] name = "async-bb8-diesel" @@ -328,7 +328,7 @@ dependencies = [ "bb8", "diesel", "thiserror", - "tokio", + "tokio 1.22.0", ] [[package]] @@ -394,7 +394,7 @@ dependencies = [ "actix-utils", "ahash", "base64", - "bytes", + "bytes 1.3.0", "cfg-if", "cookie", "derive_more", @@ -402,17 +402,17 @@ dependencies = [ "futures-util", "h2", "http", - "itoa 1.0.3", + "itoa 1.0.4", "log", "mime", "percent-encoding", - "pin-project-lite", + "pin-project-lite 0.2.9", "rand", "rustls 0.20.7", "serde", "serde_json", "serde_urlencoded", - "tokio", + "tokio 1.22.0", ] [[package]] @@ -431,13 +431,13 @@ dependencies = [ "aws-smithy-json", "aws-smithy-types", "aws-types", - "bytes", + "bytes 1.3.0", "hex", "http", "hyper", "ring", "time", - "tokio", + "tokio 1.22.0", "tower", "tracing 0.1.36", "zeroize", @@ -466,12 +466,12 @@ dependencies = [ "aws-smithy-http", "aws-smithy-types", "aws-types", - "bytes", + "bytes 1.3.0", "http", "http-body", "lazy_static", "percent-encoding", - "pin-project-lite", + "pin-project-lite 0.2.9", "tracing 0.1.36", ] @@ -491,7 +491,7 @@ dependencies = [ "aws-smithy-json", "aws-smithy-types", "aws-types", - "bytes", + "bytes 1.3.0", "http", "tokio-stream", "tower", @@ -513,7 +513,7 @@ dependencies = [ "aws-smithy-json", "aws-smithy-types", "aws-types", - "bytes", + "bytes 1.3.0", "http", "tokio-stream", "tower", @@ -536,7 +536,7 @@ dependencies = [ "aws-smithy-types", "aws-smithy-xml", "aws-types", - "bytes", + "bytes 1.3.0", "http", "tower", ] @@ -579,8 +579,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc604f278bae64bbd15854baa9c46ed69a56dfb0669d04aab80974749f2d6599" dependencies = [ "futures-util", - "pin-project-lite", - "tokio", + "pin-project-lite 0.2.9", + "tokio 1.22.0", "tokio-stream", ] @@ -594,15 +594,15 @@ dependencies = [ "aws-smithy-http", "aws-smithy-http-tower", "aws-smithy-types", - "bytes", + "bytes 1.3.0", "fastrand", "http", "http-body", "hyper", "hyper-rustls", "lazy_static", - "pin-project-lite", - "tokio", + "pin-project-lite 0.2.9", + "tokio 1.22.0", "tower", "tracing 0.1.36", ] @@ -614,7 +614,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "014a0ef5c4508fc2f6a9d3925c214725af19f020ea388db48e20196cc4cc9d6d" dependencies = [ "aws-smithy-types", - "bytes", + "bytes 1.3.0", "bytes-utils", "futures-core", "http", @@ -622,8 +622,8 @@ dependencies = [ "hyper", "once_cell", "percent-encoding", - "pin-project-lite", - "tokio", + "pin-project-lite 0.2.9", + "tokio 1.22.0", "tokio-util 0.7.4", "tracing 0.1.36", ] @@ -635,10 +635,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "deecb478dc3cc40203e0e97ac0fb92947e0719754bbafd0026bdc49318e2fd03" dependencies = [ "aws-smithy-http", - "bytes", + "bytes 1.3.0", "http", "http-body", - "pin-project-lite", + "pin-project-lite 0.2.9", "tower", "tracing 0.1.36", ] @@ -668,7 +668,7 @@ version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e93b0c93a3b963da946a0b8ef3853a7252298eb75cdbfb21dad60f5ed0ded861" dependencies = [ - "itoa 1.0.3", + "itoa 1.0.4", "num-integer", "ryu", "time", @@ -701,27 +701,27 @@ dependencies = [ [[package]] name = "axum" -version = "0.5.17" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acee9fd5073ab6b045a275b3e709c163dd36c90685219cb21804a147b58dba43" +checksum = "08b108ad2665fa3f6e6a517c3d80ec3e77d224c47d605167aefaa5d7ef97fa48" dependencies = [ "async-trait", "axum-core", "bitflags", - "bytes", + "bytes 1.3.0", "futures-util", "http", "http-body", "hyper", - "itoa 1.0.3", + "itoa 1.0.4", "matchit", "memchr", "mime", "percent-encoding", - "pin-project-lite", + "pin-project-lite 0.2.9", + "rustversion", "serde", "sync_wrapper", - "tokio", "tower", "tower-http", "tower-layer", @@ -730,25 +730,26 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.2.9" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e5939e02c56fecd5c017c37df4238c0a839fa76b7f97acdd7efb804fd181cc" +checksum = "79b8558f5a0581152dc94dcd289132a1d377494bdeafcd41869b3258e3e2ad92" dependencies = [ "async-trait", - "bytes", + "bytes 1.3.0", "futures-util", "http", "http-body", "mime", + "rustversion", "tower-layer", "tower-service", ] [[package]] name = "base64" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bb8" @@ -760,9 +761,24 @@ dependencies = [ "futures-channel", "futures-util", "parking_lot 0.12.1", - "tokio", + "tokio 1.22.0", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -810,9 +826,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.11.0" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "byteorder" @@ -822,9 +838,15 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.2.1" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" +checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" + +[[package]] +name = "bytes" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" [[package]] name = "bytes-utils" @@ -832,24 +854,24 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e47d3a8076e283f3acd27400535992edb3ba4b5bb72f8891ad8fbe7932a7d4b9" dependencies = [ - "bytes", + "bytes 1.3.0", "either", ] [[package]] name = "bytestring" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b6a75fd3048808ef06af5cd79712be8111960adaf89d90250974b38fc3928a" +checksum = "f7f83e57d9154148e355404702e2694463241880b939570d7c97c014da7a69a1" dependencies = [ - "bytes", + "bytes 1.3.0", ] [[package]] name = "cc" -version = "1.0.73" +version = "1.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" dependencies = [ "jobserver", ] @@ -879,7 +901,7 @@ dependencies = [ name = "common_utils" version = "0.1.0" dependencies = [ - "bytes", + "bytes 1.3.0", "error-stack", "masking", "router_env", @@ -983,9 +1005,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if", ] @@ -1019,7 +1041,18 @@ dependencies = [ "hashbrown", "lock_api", "once_cell", - "parking_lot_core 0.9.3", + "parking_lot_core 0.9.5", +] + +[[package]] +name = "derive_deref" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcdbcee2d9941369faba772587a565f4f534e42cb8d17e5295871de730163b2b" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1043,7 +1076,7 @@ dependencies = [ "bitflags", "byteorder", "diesel_derives", - "itoa 1.0.3", + "itoa 1.0.4", "pq-sys", "r2d2", "serde_json", @@ -1072,9 +1105,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.3", "crypto-common", @@ -1151,6 +1184,15 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "fake" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d68f517805463f3a896a9d29c1d6ff09d3579ded64a7201b4069f8f9c0d52fd" +dependencies = [ + "rand", +] + [[package]] name = "fastrand" version = "1.8.0" @@ -1162,9 +1204,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", "miniz_oxide", @@ -1218,7 +1260,7 @@ dependencies = [ "arc-swap", "arcstr", "async-trait", - "bytes", + "bytes 1.3.0", "bytes-utils", "cfg-if", "float-cmp", @@ -1232,7 +1274,7 @@ dependencies = [ "redis-protocol", "semver", "sha-1", - "tokio", + "tokio 1.22.0", "tokio-native-tls", "tokio-stream", "tokio-util 0.6.10", @@ -1289,6 +1331,16 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +[[package]] +name = "futures-locks" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c4e684ddb2d8a4db5ca8a02b35156da129674ba4412b6f528698d58c594954" +dependencies = [ + "futures", + "tokio 0.2.25", +] + [[package]] name = "futures-macro" version = "0.3.25" @@ -1325,7 +1377,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite", + "pin-project-lite 0.2.9", "pin-utils", "slab", ] @@ -1352,9 +1404,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", @@ -1388,11 +1440,11 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ - "bytes", + "bytes 1.3.0", "fnv", "futures-core", "futures-sink", @@ -1400,7 +1452,7 @@ dependencies = [ "http", "indexmap", "slab", - "tokio", + "tokio 1.22.0", "tokio-util 0.7.4", "tracing 0.1.36", ] @@ -1450,9 +1502,9 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ - "bytes", + "bytes 1.3.0", "fnv", - "itoa 1.0.3", + "itoa 1.0.4", ] [[package]] @@ -1461,9 +1513,9 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ - "bytes", + "bytes 1.3.0", "http", - "pin-project-lite", + "pin-project-lite 0.2.9", ] [[package]] @@ -1490,16 +1542,16 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" dependencies = [ - "quick-error", + "quick-error 1.2.3", ] [[package]] name = "hyper" -version = "0.14.20" +version = "0.14.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" dependencies = [ - "bytes", + "bytes 1.3.0", "futures-channel", "futures-core", "futures-util", @@ -1508,10 +1560,10 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.3", - "pin-project-lite", + "itoa 1.0.4", + "pin-project-lite 0.2.9", "socket2", - "tokio", + "tokio 1.22.0", "tower-service", "tracing 0.1.36", "want", @@ -1529,7 +1581,7 @@ dependencies = [ "log", "rustls 0.19.1", "rustls-native-certs", - "tokio", + "tokio 1.22.0", "tokio-rustls 0.22.0", "webpki 0.21.4", ] @@ -1541,8 +1593,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ "hyper", - "pin-project-lite", - "tokio", + "pin-project-lite 0.2.9", + "tokio 1.22.0", "tokio-io-timeout", ] @@ -1552,10 +1604,10 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ - "bytes", + "bytes 1.3.0", "hyper", "native-tls", - "tokio", + "tokio 1.22.0", "tokio-native-tls", ] @@ -1571,9 +1623,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown", @@ -1590,9 +1642,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" +checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745" [[package]] name = "is_ci" @@ -1617,9 +1669,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "jobserver" @@ -1682,9 +1734,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.134" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "libgit2-sys" @@ -1763,7 +1815,7 @@ dependencies = [ name = "masking" version = "0.1.0" dependencies = [ - "bytes", + "bytes 1.3.0", "diesel", "serde", "serde_json", @@ -1781,9 +1833,9 @@ dependencies = [ [[package]] name = "matchit" -version = "0.5.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" +checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" [[package]] name = "maud" @@ -1829,23 +1881,23 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.5.4" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ "libc", "log", "wasi", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -1859,9 +1911,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", @@ -1894,6 +1946,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -1915,9 +1977,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" dependencies = [ "hermit-abi", "libc", @@ -1937,9 +1999,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.42" +version = "0.10.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" +checksum = "020433887e44c27ff16365eaa2d380547a94544ad509aff6eb5b6e3e0b27b376" dependencies = [ "bitflags", "cfg-if", @@ -1969,9 +2031,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.76" +version = "0.9.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5230151e44c0f05157effb743e8d517472843121cf9243e8b81393edb5acd9ce" +checksum = "07d5c8cb6e57b3a3612064d7b18b117912b4ce70955c2504d4b741c9e244b132" dependencies = [ "autocfg", "cc", @@ -2021,7 +2083,7 @@ dependencies = [ "opentelemetry-proto", "prost", "thiserror", - "tokio", + "tokio 1.22.0", "tonic", ] @@ -2048,7 +2110,7 @@ dependencies = [ "indexmap", "js-sys", "once_cell", - "pin-project-lite", + "pin-project-lite 0.2.9", "thiserror", ] @@ -2069,7 +2131,7 @@ dependencies = [ "percent-encoding", "rand", "thiserror", - "tokio", + "tokio 1.22.0", "tokio-stream", ] @@ -2084,10 +2146,16 @@ dependencies = [ ] [[package]] -name = "owo-colors" -version = "3.4.0" +name = "overload" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "decf7381921fea4dcb2549c5667eda59b3ec297ab7e2b5fc33eac69d2e7da87b" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" dependencies = [ "supports-color", ] @@ -2110,7 +2178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.3", + "parking_lot_core 0.9.5", ] [[package]] @@ -2129,15 +2197,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -2160,9 +2228,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb779fcf4bb850fbbb0edc96ff6cf34fd90c4b1a112ce042653280d9a7364048" +checksum = "5f400b0f7905bf702f9f3dc3df5a121b16c54e9e8012c082905fdf09a931861a" dependencies = [ "thiserror", "ucd-trie", @@ -2170,9 +2238,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "502b62a6d0245378b04ffe0a7fb4f4419a4815fce813bd8a0ec89a56e07d67b1" +checksum = "423c2ba011d6e27b02b482a3707c773d19aec65cc024637aec44e19652e66f63" dependencies = [ "pest", "pest_generator", @@ -2180,9 +2248,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451e629bf49b750254da26132f1a5a9d11fd8a95a3df51d15c4abd1ba154cb6c" +checksum = "3e64e6c2c85031c02fdbd9e5c72845445ca0a724d419aa0bc068ac620c9935c1" dependencies = [ "pest", "pest_meta", @@ -2193,9 +2261,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec162c71c45e269dfc3fc2916eaeb97feab22993a21bcce4721d08cd7801a6" +checksum = "57959b91f0a133f89a68be874a5c88ed689c19cd729ecdb5d762ebf16c64d662" dependencies = [ "once_cell", "pest", @@ -2222,6 +2290,12 @@ dependencies = [ "syn", ] +[[package]] +name = "pin-project-lite" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -2236,15 +2310,15 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "pq-sys" @@ -2291,20 +2365,40 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.46" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] [[package]] -name = "prost" -version = "0.11.2" +name = "proptest" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0841812012b2d4a6145fae9a6af1534873c32aa67fff26bd09f8fa42c83f95a" +checksum = "1e0d9cc07f18492d879586c92b485def06bc850da3118075cd45d50e9c95b0e5" dependencies = [ - "bytes", + "bit-set", + "bitflags", + "byteorder", + "lazy_static", + "num-traits", + "quick-error 2.0.1", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", +] + +[[package]] +name = "prost" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b18e655c21ff5ac2084a5ad0611e827b3f92badf79f4910b5a5c58f4d87ff0" +dependencies = [ + "bytes 1.3.0", "prost-derive", ] @@ -2327,6 +2421,12 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quote" version = "1.0.21" @@ -2377,13 +2477,22 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + [[package]] name = "redis-protocol" version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c31deddf734dc0a39d3112e73490e88b61a05e83e074d211f348404cee4d2c6" dependencies = [ - "bytes", + "bytes 1.3.0", "bytes-utils", "cookie-factory", "crc16", @@ -2395,7 +2504,7 @@ dependencies = [ name = "redis_interface" version = "0.1.0" dependencies = [ - "bytes", + "bytes 1.3.0", "common_utils", "error-stack", "fred", @@ -2417,9 +2526,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" dependencies = [ "aho-corasick", "memchr", @@ -2437,9 +2546,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -2452,12 +2561,12 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.12" +version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" +checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" dependencies = [ "base64", - "bytes", + "bytes 1.3.0", "encoding_rs", "futures-core", "futures-util", @@ -2473,11 +2582,11 @@ dependencies = [ "native-tls", "once_cell", "percent-encoding", - "pin-project-lite", + "pin-project-lite 0.2.9", "serde", "serde_json", "serde_urlencoded", - "tokio", + "tokio 1.22.0", "tokio-native-tls", "tower-service", "url", @@ -2519,6 +2628,7 @@ version = "0.2.0" dependencies = [ "actix", "actix-cors", + "actix-http", "actix-rt", "actix-web", "async-bb8-diesel", @@ -2528,16 +2638,19 @@ dependencies = [ "aws-sdk-kms", "base64", "bb8", - "bytes", + "bytes 1.3.0", "common_utils", "config", "crc32fast", + "derive_deref", "diesel", "dyn-clone", "encoding_rs", "error-stack", + "fake", "fred", "futures", + "futures-locks", "hex", "http", "josekit", @@ -2547,6 +2660,7 @@ dependencies = [ "mime", "nanoid", "once_cell", + "proptest", "rand", "redis_interface", "regex", @@ -2563,7 +2677,7 @@ dependencies = [ "strum", "thiserror", "time", - "tokio", + "tokio 1.22.0", "toml", "url", "uuid", @@ -2597,13 +2711,14 @@ dependencies = [ "serde_urlencoded", "strum", "time", - "tokio", + "tokio 1.22.0", "tracing 0.1.36", "tracing-actix-web", "tracing-appender", - "tracing-core 0.1.29", + "tracing-attributes", + "tracing-core 0.1.30", "tracing-opentelemetry 0.16.0", - "tracing-subscriber 0.3.15", + "tracing-subscriber 0.3.16", "vergen", ] @@ -2675,6 +2790,18 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error 1.2.3", + "tempfile", + "wait-timeout", +] + [[package]] name = "ryu" version = "1.0.11" @@ -2688,7 +2815,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -2782,7 +2909,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" dependencies = [ "indexmap", - "itoa 1.0.3", + "itoa 1.0.4", "ryu", "serde", ] @@ -2805,7 +2932,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.3", + "itoa 1.0.4", "ryu", "serde", ] @@ -2831,7 +2958,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -2842,7 +2969,7 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -2874,9 +3001,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "socket2" @@ -2948,9 +3075,9 @@ dependencies = [ [[package]] name = "supports-color" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4872ced36b91d47bae8a214a683fe54e7078875b399dfa251df346c9b547d1f9" +checksum = "8ba6faf2ca7ee42fdd458f4347ae0a9bd6bcc445ad7cb57ad82b383f18870d6f" dependencies = [ "atty", "is_ci", @@ -2958,9 +3085,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.104" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae548ec36cf198c0ef7710d3c230987c2d6d7bd98ad6edc0274462724c585ce" +checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" dependencies = [ "proc-macro2", "quote", @@ -2975,9 +3102,9 @@ checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" [[package]] name = "sysinfo" -version = "0.26.4" +version = "0.26.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7890fff842b8db56f2033ebee8f6efe1921475c3830c115995552914fb967580" +checksum = "29ddf41e393a9133c81d5f0974195366bd57082deac6e0eb02ed39b8341c2bb6" dependencies = [ "cfg-if", "core-foundation-sys", @@ -3054,7 +3181,7 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" dependencies = [ - "itoa 1.0.3", + "itoa 1.0.4", "serde", "time-core", "time-macros", @@ -3092,18 +3219,29 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.21.2" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" +checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092" +dependencies = [ + "bytes 0.5.6", + "pin-project-lite 0.1.12", + "slab", +] + +[[package]] +name = "tokio" +version = "1.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3" dependencies = [ "autocfg", - "bytes", + "bytes 1.3.0", "libc", "memchr", "mio", "num_cpus", "parking_lot 0.12.1", - "pin-project-lite", + "pin-project-lite 0.2.9", "signal-hook-registry", "socket2", "tokio-macros", @@ -3116,15 +3254,15 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" dependencies = [ - "pin-project-lite", - "tokio", + "pin-project-lite 0.2.9", + "tokio 1.22.0", ] [[package]] name = "tokio-macros" -version = "1.8.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ "proc-macro2", "quote", @@ -3138,7 +3276,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" dependencies = [ "native-tls", - "tokio", + "tokio 1.22.0", ] [[package]] @@ -3148,7 +3286,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" dependencies = [ "rustls 0.19.1", - "tokio", + "tokio 1.22.0", "webpki 0.21.4", ] @@ -3159,19 +3297,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ "rustls 0.20.7", - "tokio", + "tokio 1.22.0", "webpki 0.22.0", ] [[package]] name = "tokio-stream" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6edf2d6bc038a43d31353570e27270603f4648d18f5ed10c0e179abe43255af" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" dependencies = [ "futures-core", - "pin-project-lite", - "tokio", + "pin-project-lite 0.2.9", + "tokio 1.22.0", ] [[package]] @@ -3180,12 +3318,12 @@ version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" dependencies = [ - "bytes", + "bytes 1.3.0", "futures-core", "futures-sink", "log", - "pin-project-lite", - "tokio", + "pin-project-lite 0.2.9", + "tokio 1.22.0", ] [[package]] @@ -3194,11 +3332,11 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ - "bytes", + "bytes 1.3.0", "futures-core", "futures-sink", - "pin-project-lite", - "tokio", + "pin-project-lite 0.2.9", + "tokio 1.22.0", "tracing 0.1.36", ] @@ -3213,15 +3351,15 @@ dependencies = [ [[package]] name = "tonic" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55b9af819e54b8f33d453655bef9b9acc171568fb49523078d0cc4e7484200ec" +checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb" dependencies = [ "async-stream", "async-trait", "axum", "base64", - "bytes", + "bytes 1.3.0", "futures-core", "futures-util", "h2", @@ -3233,7 +3371,7 @@ dependencies = [ "pin-project", "prost", "prost-derive", - "tokio", + "tokio 1.22.0", "tokio-stream", "tokio-util 0.7.4", "tower", @@ -3253,10 +3391,10 @@ dependencies = [ "futures-util", "indexmap", "pin-project", - "pin-project-lite", + "pin-project-lite 0.2.9", "rand", "slab", - "tokio", + "tokio 1.22.0", "tokio-util 0.7.4", "tower-layer", "tower-service", @@ -3270,13 +3408,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c530c8675c1dbf98facee631536fa116b5fb6382d7dd6dc1b118d970eafe3ba" dependencies = [ "bitflags", - "bytes", + "bytes 1.3.0", "futures-core", "futures-util", "http", "http-body", "http-range-header", - "pin-project-lite", + "pin-project-lite 0.2.9", "tower", "tower-layer", "tower-service", @@ -3284,9 +3422,9 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" [[package]] name = "tower-service" @@ -3302,9 +3440,9 @@ checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" dependencies = [ "cfg-if", "log", - "pin-project-lite", + "pin-project-lite 0.2.9", "tracing-attributes", - "tracing-core 0.1.29", + "tracing-core 0.1.30", ] [[package]] @@ -3313,15 +3451,15 @@ version = "0.2.0" source = "git+https://github.com/jarnura/tracing?rev=16d277227f60788750528e4f4cc1db4f36b0869f#16d277227f60788750528e4f4cc1db4f36b0869f" dependencies = [ "cfg-if", - "pin-project-lite", + "pin-project-lite 0.2.9", "tracing-core 0.2.0", ] [[package]] name = "tracing-actix-web" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee7247a77b494ee07bda43bce40a33e76f885662f11b3dda9894ecfdbe31fa06" +checksum = "d725b8fa6ef307b3f4856913523337de45c47cc79271bafd7acfb39559e3a2da" dependencies = [ "actix-web", "opentelemetry 0.17.0", @@ -3339,7 +3477,7 @@ checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e" dependencies = [ "crossbeam-channel", "time", - "tracing-subscriber 0.3.15", + "tracing-subscriber 0.3.16", ] [[package]] @@ -3355,9 +3493,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", "valuable", @@ -3389,7 +3527,7 @@ checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" dependencies = [ "lazy_static", "log", - "tracing-core 0.1.29", + "tracing-core 0.1.30", ] [[package]] @@ -3425,9 +3563,9 @@ dependencies = [ "once_cell", "opentelemetry 0.17.0", "tracing 0.1.36", - "tracing-core 0.1.29", + "tracing-core 0.1.30", "tracing-log 0.1.3", - "tracing-subscriber 0.3.15", + "tracing-subscriber 0.3.16", ] [[package]] @@ -3437,7 +3575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" dependencies = [ "serde", - "tracing-core 0.1.29", + "tracing-core 0.1.30", ] [[package]] @@ -3452,12 +3590,12 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" +checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" dependencies = [ - "ansi_term", "matchers", + "nu-ansi-term", "once_cell", "regex", "serde", @@ -3466,7 +3604,7 @@ dependencies = [ "smallvec", "thread_local", "tracing 0.1.36", - "tracing-core 0.1.29", + "tracing-core 0.1.30", "tracing-log 0.1.3", "tracing-serde", ] @@ -3497,9 +3635,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-normalization" @@ -3548,9 +3686,9 @@ checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" [[package]] name = "uuid" -version = "1.1.2" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f" +checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c" dependencies = [ "getrandom", "serde", @@ -3576,9 +3714,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "vergen" -version = "7.4.2" +version = "7.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ba753d713ec3844652ad2cb7eb56bc71e34213a14faddac7852a10ba88f61e" +checksum = "447f9238a4553957277b3ee09d80babeae0811f1b3baefb093de1c0448437a37" dependencies = [ "anyhow", "cfg-if", @@ -3598,6 +3736,15 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "want" version = "0.3.0" @@ -3756,43 +3903,100 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", ] +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + [[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + [[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + [[package]] name = "winreg" version = "0.10.1" @@ -3844,9 +4048,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.1+zstd.1.5.2" +version = "2.0.4+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" +checksum = "4fa202f2ef00074143e219d15b62ffc317d17cc33909feac471c044087cad7b0" dependencies = [ "cc", "libc", diff --git a/Makefile b/Makefile index c61b60dbd2..f92b3d583f 100644 --- a/Makefile +++ b/Makefile @@ -75,6 +75,15 @@ clippy : test : cargo test --all-features + +# Next-generation test runner for Rust. +# cargo nextest ignores the doctests at the moment. So if you are using it locally you also have to run `cargo test --doc`. +# Usage: +# make nextest + +nextest: + cargo nextest run + # Run format clippy test and tests. # # Usage : diff --git a/crates/masking/README.md b/crates/masking/README.md index 0e2d9e043f..e17a0b5443 100644 --- a/crates/masking/README.md +++ b/crates/masking/README.md @@ -8,24 +8,24 @@ Secret-keeping library inspired by `secrecy`. To convert non-secret variable into secret use `new()`. Sample: -```rust +```rust,ignore expiry_year: ccard.map(|x| Secret::new(x.card_exp_year.to_string())), // output: "expiry_year: *** alloc::string::String ***" ``` To get value from secret use `expose()`. Sample: -```rust ignore -last4_digits: Some(card_number.peek().clone()) +```rust,ignore +last4_digits: Some(card_number.expose()) ``` Most fields are under `Option`. To simplify dealing with `Option`, use `expose_cloning()`. Sample: -```rust +```rust,ignore card_info.push_str( &card_detail .card_holder_name - .peek_cloning() + .expose_cloning() .unwrap_or_default(), ); ``` diff --git a/crates/masking/src/secret.rs b/crates/masking/src/secret.rs index b37946b8e0..07e861a0e3 100644 --- a/crates/masking/src/secret.rs +++ b/crates/masking/src/secret.rs @@ -9,7 +9,7 @@ use crate::{strategy::Strategy, PeekInterface}; /// /// Secret thing. /// -/// To get access to value use method `expose()` of trait [`ExposeInterface`]. +/// To get access to value use method `expose()` of trait [`crate::ExposeInterface`]. /// /// ## Masking /// Use the [`crate::strategy::Strategy`] trait to implement a masking strategy on a unit struct diff --git a/crates/masking/src/serde.rs b/crates/masking/src/serde.rs index dfdb14a9d2..8903ca4516 100644 --- a/crates/masking/src/serde.rs +++ b/crates/masking/src/serde.rs @@ -9,7 +9,7 @@ use crate::{PeekInterface, Secret, Strategy, StrongSecret, ZeroizableSecret}; /// Marker trait for secret types which can be [`Serialize`]-d by [`serde`]. /// /// When the `serde` feature of this crate is enabled and types are marked with -/// this trait, they receive a [`Serialize` impl][1] for `Secret`. +/// this trait, they receive a [`Serialize` impl] for `Secret`. /// (NOTE: all types which impl `DeserializeOwned` receive a [`Deserialize`] /// impl) /// diff --git a/crates/masking/src/strategy.rs b/crates/masking/src/strategy.rs index f094d88a04..3d981675e7 100644 --- a/crates/masking/src/strategy.rs +++ b/crates/masking/src/strategy.rs @@ -33,6 +33,6 @@ where T: fmt::Display, { fn fmt(val: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&format!("{}", val)) + fmt::Display::fmt(val, f) } } diff --git a/crates/masking/src/strong_secret.rs b/crates/masking/src/strong_secret.rs index e149ff05f2..d5d6ffe639 100644 --- a/crates/masking/src/strong_secret.rs +++ b/crates/masking/src/strong_secret.rs @@ -11,7 +11,7 @@ use crate::{strategy::Strategy, PeekInterface}; /// /// Secret thing. /// -/// To get access to value use method `expose()` of trait [`ExposeInterface`]. +/// To get access to value use method `expose()` of trait [`crate::ExposeInterface`]. /// pub struct StrongSecret { diff --git a/crates/redis_interface/src/lib.rs b/crates/redis_interface/src/lib.rs index ae23b53b99..c26992e3b8 100644 --- a/crates/redis_interface/src/lib.rs +++ b/crates/redis_interface/src/lib.rs @@ -100,6 +100,6 @@ mod test { fn test_redis_error() { let x = errors::RedisError::ConsumerGroupClaimFailed.to_string(); - assert_eq!(x, "Failed to set redis stream message owner".to_string()) + assert_eq!(x, "Failed to set Redis stream message owner".to_string()) } } diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml index 4afd89f420..afbb401c14 100644 --- a/crates/router/Cargo.toml +++ b/crates/router/Cargo.toml @@ -7,10 +7,9 @@ default-run = "router" rust-version = "1.63" readme = "README.md" license = "Apache-2.0" -build = "src/build.rs" [features] -default = [] +default = ["kv_store"] kms = ["aws-config", "aws-sdk-kms"] basilisk = [] stripe = ["dep:serde_qs"] @@ -26,7 +25,7 @@ actix-cors = "0.6.3" actix-rt = "2.7.0" actix-web = "4.2.1" async-bb8-diesel = { git = "https://github.com/juspay/async-bb8-diesel", rev = "412663e16802dbc58a1b98bfcbe78fa0090311eb" } -async-trait = { version = "0.1.57" } +async-trait = "0.1.57" aws-config = { version = "0.49.0", optional = true } aws-sdk-kms = { version = "0.19.0", optional = true } base64 = "0.13.0" @@ -63,6 +62,7 @@ time = { version = "0.3.14", features = ["serde", "serde-well-known", "std"] } tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] } url = { version = "2.3.1", features = ["serde"] } uuid = { version = "1.1.2", features = ["serde", "v4"] } +futures-locks = "0.6" futures = "0.3" # First party crates @@ -72,14 +72,19 @@ redis_interface = { version = "0.1.0", path = "../redis_interface" } router_derive = { version = "0.1.0", path = "../router_derive" } router_env = { version = "0.1.0", path = "../router_env", features = ["log_extra_implicit_fields", "log_custom_entries_to_extra"] } +[build-dependencies] +router_env = { version = "0.1.0", path = "../router_env", default-features = false, features = ["vergen"] } + [dev-dependencies] awc = { version = "3.0.1", features = ["rustls"] } time = { version = "0.3.14", features = ["macros"] } tokio = "1.21.2" toml = "0.5.9" - -[build-dependencies] -router_env = { version = "0.1.0", path = "../router_env", default-features = false, features = ["vergen"] } +derive_deref = "1.1.1" +actix-http = "3.2.2" +proptest = "1.0" +fake = "2.5" +rand = "0.8" [[bin]] name = "router" diff --git a/crates/router/build.rs b/crates/router/build.rs new file mode 100644 index 0000000000..4b07385af6 --- /dev/null +++ b/crates/router/build.rs @@ -0,0 +1,3 @@ +fn main() { + router_env::vergen::generate_cargo_instructions(); +} diff --git a/crates/router/sqlx-data.json b/crates/router/sqlx-data.json new file mode 100644 index 0000000000..cb93a01004 --- /dev/null +++ b/crates/router/sqlx-data.json @@ -0,0 +1,400 @@ +{ + "db": "PostgreSQL", + "81517ed4dc151e2b267f997f62aff37bb86b3e22f6b0446e9d9c835a3b20439c": { + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Int4" + }, + { + "name": "customer_id", + "ordinal": 1, + "type_info": "Varchar" + }, + { + "name": "merchant_id", + "ordinal": 2, + "type_info": "Varchar" + }, + { + "name": "name", + "ordinal": 3, + "type_info": "Varchar" + }, + { + "name": "email: _", + "ordinal": 4, + "type_info": "Varchar" + }, + { + "name": "phone: _", + "ordinal": 5, + "type_info": "Varchar" + }, + { + "name": "phone_country_code", + "ordinal": 6, + "type_info": "Varchar" + }, + { + "name": "description", + "ordinal": 7, + "type_info": "Varchar" + }, + { + "name": "address: _", + "ordinal": 8, + "type_info": "Json" + }, + { + "name": "created_at", + "ordinal": 9, + "type_info": "Timestamp" + }, + { + "name": "metadata", + "ordinal": 10, + "type_info": "Json" + } + ], + "nullable": [ + false, + false, + false, + true, + true, + true, + true, + true, + true, + false, + true + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + } + }, + "query": "\n SELECT\n \"customers\".\"id\",\n \"customers\".\"customer_id\",\n \"customers\".\"merchant_id\",\n \"customers\".\"name\",\n \"customers\".\"email\" as \"email: _\",\n \"customers\".\"phone\" as \"phone: _\",\n \"customers\".\"phone_country_code\",\n \"customers\".\"description\",\n \"customers\".\"address\" as \"address: _\",\n \"customers\".\"created_at\",\n \"customers\".\"metadata\"\n FROM\n \"customers\"\n WHERE\n (\n (\"customers\".\"customer_id\" = $1)\n AND (\"customers\".\"merchant_id\" = $2)\n )" + }, + "d184fdec6428364a6e4e2517a4d36af85141d973085d7ab78137d43d3c97364a": { + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Int4" + }, + { + "name": "merchant_id", + "ordinal": 1, + "type_info": "Varchar" + }, + { + "name": "connector_name", + "ordinal": 2, + "type_info": "Varchar" + }, + { + "name": "connector_account_details", + "ordinal": 3, + "type_info": "Json" + }, + { + "name": "test_mode", + "ordinal": 4, + "type_info": "Bool" + }, + { + "name": "disabled", + "ordinal": 5, + "type_info": "Bool" + }, + { + "name": "merchant_connector_id", + "ordinal": 6, + "type_info": "Int4" + }, + { + "name": "payment_methods_enabled", + "ordinal": 7, + "type_info": "JsonArray" + }, + { + "name": "connector_type: _", + "ordinal": 8, + "type_info": { + "Custom": { + "kind": { + "Enum": [ + "payment_processor", + "payment_vas", + "fin_operations", + "fiz_operations", + "networks", + "banking_entities", + "non_banking_finance" + ] + }, + "name": "ConnectorType" + } + } + } + ], + "nullable": [ + false, + false, + false, + false, + true, + true, + false, + true, + false + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + } + }, + "query": "\n SELECT\n \"merchant_connector_account\".\"id\",\n \"merchant_connector_account\".\"merchant_id\",\n \"merchant_connector_account\".\"connector_name\",\n \"merchant_connector_account\".\"connector_account_details\",\n \"merchant_connector_account\".\"test_mode\",\n \"merchant_connector_account\".\"disabled\",\n \"merchant_connector_account\".\"merchant_connector_id\",\n \"merchant_connector_account\".\"payment_methods_enabled\",\n \"merchant_connector_account\".\"connector_type\" \"connector_type: _\"\n FROM\n \"merchant_connector_account\"\n WHERE\n (\n (\n \"merchant_connector_account\".\"merchant_id\" = $1\n )\n AND (\n \"merchant_connector_account\".\"connector_name\" = $2\n )\n )" + }, + "fbef5d3470d67da1a07a2189c80ecc711d3d4fcd4887cc7ceb8944b93843da16": { + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Int4" + }, + { + "name": "merchant_id", + "ordinal": 1, + "type_info": "Varchar" + }, + { + "name": "api_key: _", + "ordinal": 2, + "type_info": "Varchar" + }, + { + "name": "return_url", + "ordinal": 3, + "type_info": "Varchar" + }, + { + "name": "enable_payment_response_hash", + "ordinal": 4, + "type_info": "Bool" + }, + { + "name": "payment_response_hash_key", + "ordinal": 5, + "type_info": "Varchar" + }, + { + "name": "redirect_to_merchant_with_http_post", + "ordinal": 6, + "type_info": "Bool" + }, + { + "name": "merchant_name", + "ordinal": 7, + "type_info": "Varchar" + }, + { + "name": "merchant_details", + "ordinal": 8, + "type_info": "Json" + }, + { + "name": "webhook_details", + "ordinal": 9, + "type_info": "Json" + }, + { + "name": "routing_algorithm: _", + "ordinal": 10, + "type_info": { + "Custom": { + "kind": { + "Enum": [ + "round_robin", + "max_conversion", + "min_cost", + "custom" + ] + }, + "name": "RoutingAlgorithm" + } + } + }, + { + "name": "custom_routing_rules", + "ordinal": 11, + "type_info": "Json" + }, + { + "name": "sub_merchants_enabled", + "ordinal": 12, + "type_info": "Bool" + }, + { + "name": "parent_merchant_id", + "ordinal": 13, + "type_info": "Varchar" + }, + { + "name": "publishable_key", + "ordinal": 14, + "type_info": "Varchar" + } + ], + "nullable": [ + false, + false, + true, + true, + false, + true, + false, + true, + true, + true, + true, + true, + true, + true, + true + ], + "parameters": { + "Left": [ + "Text" + ] + } + }, + "query": "\n SELECT\n \"merchant_account\".\"id\",\n \"merchant_account\".\"merchant_id\",\n \"merchant_account\".\"api_key\" as \"api_key: _\",\n \"merchant_account\".\"return_url\",\n \"merchant_account\".\"enable_payment_response_hash\",\n \"merchant_account\".\"payment_response_hash_key\",\n \"merchant_account\".\"redirect_to_merchant_with_http_post\",\n \"merchant_account\".\"merchant_name\",\n \"merchant_account\".\"merchant_details\",\n \"merchant_account\".\"webhook_details\",\n \"merchant_account\".\"routing_algorithm\" as \"routing_algorithm: _\",\n \"merchant_account\".\"custom_routing_rules\",\n \"merchant_account\".\"sub_merchants_enabled\",\n \"merchant_account\".\"parent_merchant_id\",\n \"merchant_account\".\"publishable_key\"\n FROM\n \"merchant_account\"\n WHERE\n (\n \"merchant_account\".\"merchant_id\" = $1\n )\n " + }, + "fd48a272a849cfb042c961467adb38e929da5552ca008a878ca84cb4f4f75121": { + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Int4" + }, + { + "name": "merchant_id", + "ordinal": 1, + "type_info": "Varchar" + }, + { + "name": "api_key: _", + "ordinal": 2, + "type_info": "Varchar" + }, + { + "name": "return_url", + "ordinal": 3, + "type_info": "Varchar" + }, + { + "name": "enable_payment_response_hash", + "ordinal": 4, + "type_info": "Bool" + }, + { + "name": "payment_response_hash_key", + "ordinal": 5, + "type_info": "Varchar" + }, + { + "name": "redirect_to_merchant_with_http_post", + "ordinal": 6, + "type_info": "Bool" + }, + { + "name": "merchant_name", + "ordinal": 7, + "type_info": "Varchar" + }, + { + "name": "merchant_details", + "ordinal": 8, + "type_info": "Json" + }, + { + "name": "webhook_details", + "ordinal": 9, + "type_info": "Json" + }, + { + "name": "routing_algorithm: _", + "ordinal": 10, + "type_info": { + "Custom": { + "kind": { + "Enum": [ + "round_robin", + "max_conversion", + "min_cost", + "custom" + ] + }, + "name": "RoutingAlgorithm" + } + } + }, + { + "name": "custom_routing_rules", + "ordinal": 11, + "type_info": "Json" + }, + { + "name": "sub_merchants_enabled", + "ordinal": 12, + "type_info": "Bool" + }, + { + "name": "parent_merchant_id", + "ordinal": 13, + "type_info": "Varchar" + }, + { + "name": "publishable_key", + "ordinal": 14, + "type_info": "Varchar" + } + ], + "nullable": [ + false, + false, + true, + true, + false, + true, + false, + true, + true, + true, + true, + true, + true, + true, + true + ], + "parameters": { + "Left": [ + "Text" + ] + } + }, + "query": "\n SELECT\n \"merchant_account\".\"id\",\n \"merchant_account\".\"merchant_id\",\n \"merchant_account\".\"api_key\" as \"api_key: _\",\n \"merchant_account\".\"return_url\",\n \"merchant_account\".\"enable_payment_response_hash\",\n \"merchant_account\".\"payment_response_hash_key\",\n \"merchant_account\".\"redirect_to_merchant_with_http_post\",\n \"merchant_account\".\"merchant_name\",\n \"merchant_account\".\"merchant_details\",\n \"merchant_account\".\"webhook_details\",\n \"merchant_account\".\"routing_algorithm\" as \"routing_algorithm: _\",\n \"merchant_account\".\"custom_routing_rules\",\n \"merchant_account\".\"sub_merchants_enabled\",\n \"merchant_account\".\"parent_merchant_id\",\n \"merchant_account\".\"publishable_key\"\n FROM\n \"merchant_account\"\n WHERE\n (\n \"merchant_account\".\"api_key\" = $1\n )\n " + } +} \ No newline at end of file diff --git a/crates/router/src/bin/router.rs b/crates/router/src/bin/router.rs index 92689f1400..9fcecfcdb3 100644 --- a/crates/router/src/bin/router.rs +++ b/crates/router/src/bin/router.rs @@ -20,10 +20,7 @@ async fn main() -> BachResult<()> { let _ = server.await; - std::sync::Arc::get_mut(&mut state.store.redis_conn) - .expect("Redis connection pool cannot be closed") - .close_connections() - .await; + state.store.close().await; Err(BachError::from(std::io::Error::new( std::io::ErrorKind::Other, diff --git a/crates/router/src/bin/scheduler.rs b/crates/router/src/bin/scheduler.rs index c8f8ef291b..7d75354244 100644 --- a/crates/router/src/bin/scheduler.rs +++ b/crates/router/src/bin/scheduler.rs @@ -5,7 +5,6 @@ use router::{ configs::settings::{CmdLineConf, Settings}, core::errors::{self, CustomResult}, logger, routes, scheduler, - services::Store, }; use structopt::StructOpt; @@ -17,11 +16,7 @@ async fn main() -> CustomResult<(), errors::ProcessTrackerError> { let cmd_line = CmdLineConf::from_args(); let conf = Settings::with_config_path(cmd_line.config_path).unwrap(); - let mut state = routes::AppState { - flow_name: String::from("default"), - store: Store::new(&conf).await, - conf, - }; + let mut state = routes::AppState::new(conf).await; let _guard = logger::setup(&state.conf.log).map_err(|_| errors::ProcessTrackerError::UnexpectedFlow)?; @@ -29,10 +24,7 @@ async fn main() -> CustomResult<(), errors::ProcessTrackerError> { start_scheduler(&state).await?; - std::sync::Arc::get_mut(&mut state.store.redis_conn) - .expect("Redis connection pool cannot be closed") - .close_connections() - .await; + state.store.close().await; eprintln!("Scheduler shut down"); Ok(()) diff --git a/crates/router/src/compatibility/stripe/customers.rs b/crates/router/src/compatibility/stripe/customers.rs index 24ea1eda6f..0623da5bf3 100644 --- a/crates/router/src/compatibility/stripe/customers.rs +++ b/crates/router/src/compatibility/stripe/customers.rs @@ -34,7 +34,7 @@ pub async fn customer_create( &req, create_cust_req, |state, merchant_account, req| { - customers::create_customer(&state.store, merchant_account, req) + customers::create_customer(&*state.store, merchant_account, req) }, api::MerchantAuthentication::ApiKey, ) @@ -57,7 +57,7 @@ pub async fn customer_retrieve( &req, payload, |state, merchant_account, req| { - customers::retrieve_customer(&state.store, merchant_account, req) + customers::retrieve_customer(&*state.store, merchant_account, req) }, api::MerchantAuthentication::ApiKey, ) @@ -89,7 +89,7 @@ pub async fn customer_update( &req, cust_update_req, |state, merchant_account, req| { - customers::update_customer(&state.store, merchant_account, req) + customers::update_customer(&*state.store, merchant_account, req) }, api::MerchantAuthentication::ApiKey, ) @@ -112,7 +112,7 @@ pub async fn customer_delete( &req, payload, |state, merchant_account, req| { - customers::delete_customer(&state.store, merchant_account, req) + customers::delete_customer(&*state.store, merchant_account, req) }, api::MerchantAuthentication::ApiKey, ) diff --git a/crates/router/src/compatibility/stripe/payment_intents.rs b/crates/router/src/compatibility/stripe/payment_intents.rs index c7ba7dac32..3591562687 100644 --- a/crates/router/src/compatibility/stripe/payment_intents.rs +++ b/crates/router/src/compatibility/stripe/payment_intents.rs @@ -341,7 +341,9 @@ pub async fn payment_intent_list( &state, &req, payload, - |state, merchant_account, req| payments::list_payments(&state.store, merchant_account, req), + |state, merchant_account, req| { + payments::list_payments(&*state.store, merchant_account, req) + }, api::MerchantAuthentication::ApiKey, ) .await diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs index 1fedee47eb..9aca230621 100644 --- a/crates/router/src/compatibility/stripe/payment_intents/types.rs +++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs @@ -1,4 +1,3 @@ -use common_utils::custom_serde; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -257,7 +256,7 @@ pub(crate) struct StripePaymentIntentResponse { pub(crate) currency: String, pub(crate) status: StripePaymentStatus, pub(crate) client_secret: Option>, - #[serde(with = "custom_serde::iso8601::option")] + #[serde(with = "common_utils::custom_serde::iso8601::option")] pub(crate) created: Option, pub(crate) customer: Option, pub(crate) refunds: Option>, diff --git a/crates/router/src/compatibility/stripe/refunds.rs b/crates/router/src/compatibility/stripe/refunds.rs index 62565c18e9..cdeb26113b 100644 --- a/crates/router/src/compatibility/stripe/refunds.rs +++ b/crates/router/src/compatibility/stripe/refunds.rs @@ -92,7 +92,7 @@ pub(crate) async fn refund_update( &req, create_refund_update_req, |state, merchant_account, req| { - refunds::refund_update_core(&state.store, merchant_account, &refund_id, req) + refunds::refund_update_core(&*state.store, merchant_account, &refund_id, req) }, api::MerchantAuthentication::ApiKey, ) diff --git a/crates/router/src/connection.rs b/crates/router/src/connection.rs index 7e5dd4ca94..9a5d921f2c 100644 --- a/crates/router/src/connection.rs +++ b/crates/router/src/connection.rs @@ -2,9 +2,10 @@ use async_bb8_diesel::{AsyncConnection, ConnectionError, ConnectionManager}; use bb8::{CustomizeConnection, PooledConnection}; use diesel::PgConnection; -use crate::configs::settings::{Database, Settings}; +use crate::configs::settings::Database; pub type PgPool = bb8::Pool>; + pub type PgPooledConn = async_bb8_diesel::Connection; pub type RedisPool = std::sync::Arc; @@ -25,12 +26,14 @@ impl CustomizeConnection for TestTransaction { } } -pub async fn redis_connection(conf: &Settings) -> redis_interface::RedisConnectionPool { +pub async fn redis_connection( + conf: &crate::configs::settings::Settings, +) -> redis_interface::RedisConnectionPool { redis_interface::RedisConnectionPool::new(&conf.redis).await } #[allow(clippy::expect_used)] -pub async fn make_pg_pool(database: &Database, test_transaction: bool) -> PgPool { +pub async fn diesel_make_pg_pool(database: &Database, test_transaction: bool) -> PgPool { let database_url = format!( "postgres://{}:{}@{}:{}/{}", database.username, database.password, database.host, database.port, database.dbname diff --git a/crates/router/src/connector/adyen.rs b/crates/router/src/connector/adyen.rs index cce42e2507..a4369d69f1 100644 --- a/crates/router/src/connector/adyen.rs +++ b/crates/router/src/connector/adyen.rs @@ -10,11 +10,11 @@ use router_env::{tracing, tracing::instrument}; use self::transformers as adyen; use crate::{ configs::settings::Connectors, - connection, core::{ errors::{self, CustomResult}, payments, }, + db::StorageInterface, headers, logger, services, types::{ self, @@ -550,12 +550,12 @@ impl api::IncomingWebhook for Adyen { async fn get_webhook_source_verification_merchant_secret( &self, + db: &dyn StorageInterface, merchant_id: &str, - redis_conn: connection::RedisPool, ) -> CustomResult, errors::ConnectorError> { let key = format!("whsec_verification_{}_{}", self.id(), merchant_id); - let secret = redis_conn - .get_key::>(&key) + let secret = db + .get_key(&key) .await .change_context(errors::ConnectorError::WebhookVerificationSecretNotFound)?; diff --git a/crates/router/src/connector/stripe.rs b/crates/router/src/connector/stripe.rs index 7181b87610..2e7dac4b82 100644 --- a/crates/router/src/connector/stripe.rs +++ b/crates/router/src/connector/stripe.rs @@ -9,8 +9,9 @@ use router_env::{tracing, tracing::instrument}; use self::transformers as stripe; use crate::{ configs::settings::Connectors, - connection, consts, + consts, core::errors::{self, CustomResult}, + db::StorageInterface, headers, logger, services, types::{ self, @@ -747,12 +748,12 @@ impl api::IncomingWebhook for Stripe { async fn get_webhook_source_verification_merchant_secret( &self, + db: &dyn StorageInterface, merchant_id: &str, - redis_conn: connection::RedisPool, ) -> CustomResult, errors::ConnectorError> { let key = format!("whsec_verification_{}_{}", self.id(), merchant_id); - let secret = redis_conn - .get_key::>(&key) + let secret = db + .get_key(&key) .await .change_context(errors::ConnectorError::WebhookVerificationSecretNotFound)?; diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index 9c1d1112fd..947610868a 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -3,13 +3,10 @@ use uuid::Uuid; use crate::{ core::errors::{self, RouterResponse, RouterResult, StorageErrorExt}, - db::{ - merchant_account::IMerchantAccount, merchant_connector_account::IMerchantConnectorAccount, - Db, - }, + db::StorageInterface, env::{self, Env}, pii::Secret, - services::{api as service_api, Store}, + services::api as service_api, types::{ self, api, storage::{self, MerchantAccount}, @@ -27,7 +24,7 @@ fn create_merchant_api_key() -> String { } pub async fn create_merchant_account( - db: &dyn Db, + db: &dyn StorageInterface, req: api::CreateMerchantAccount, ) -> RouterResponse { let publishable_key = &format!("pk_{}", create_merchant_api_key()); @@ -82,7 +79,7 @@ pub async fn create_merchant_account( } pub async fn get_merchant_account( - db: &dyn Db, + db: &dyn StorageInterface, req: api::MerchantId, ) -> RouterResponse { let merchant_account = db @@ -129,7 +126,7 @@ pub async fn get_merchant_account( } pub async fn merchant_account_update( - db: &dyn Db, + db: &dyn StorageInterface, merchant_id: &String, req: api::CreateMerchantAccount, ) -> RouterResponse { @@ -213,7 +210,7 @@ pub async fn merchant_account_update( } pub async fn merchant_account_delete( - db: &dyn Db, + db: &dyn StorageInterface, merchant_id: String, ) -> RouterResponse { let is_deleted = db @@ -230,7 +227,7 @@ pub async fn merchant_account_delete( } async fn get_parent_merchant( - db: &dyn Db, + db: &dyn StorageInterface, sub_merchants_enabled: &Option, parent_merchant: Option, ) -> RouterResult> { @@ -260,7 +257,7 @@ async fn get_parent_merchant( } async fn validate_merchant_id>( - db: &dyn Db, + db: &dyn StorageInterface, merchant_id: S, ) -> RouterResult { db.find_merchant_account_by_merchant_id(&merchant_id.into()) @@ -273,7 +270,7 @@ async fn validate_merchant_id>( // with unique merchant_connector_id for Create Operation pub async fn create_payment_connector( - store: &Store, + store: &dyn StorageInterface, req: api::PaymentConnectorCreate, merchant_id: &String, ) -> RouterResponse { @@ -331,7 +328,7 @@ pub async fn create_payment_connector( } pub async fn retrieve_payment_connector( - store: &Store, + store: &dyn StorageInterface, merchant_id: String, merchant_connector_id: i32, ) -> RouterResponse { @@ -364,7 +361,7 @@ pub async fn retrieve_payment_connector( } pub async fn update_payment_connector( - db: &dyn Db, + db: &dyn StorageInterface, merchant_id: &str, merchant_connector_id: i32, req: api::PaymentConnectorCreate, @@ -429,7 +426,7 @@ pub async fn update_payment_connector( } pub async fn delete_payment_connector( - db: &dyn Db, + db: &dyn StorageInterface, merchant_id: String, merchant_connector_id: i32, ) -> RouterResponse { diff --git a/crates/router/src/core/customers.rs b/crates/router/src/core/customers.rs index 22e8cff99e..1b4b2a0148 100644 --- a/crates/router/src/core/customers.rs +++ b/crates/router/src/core/customers.rs @@ -3,14 +3,14 @@ use router_env::{tracing, tracing::instrument}; use crate::{ core::errors::{self, RouterResponse, StorageErrorExt}, - db::Db, + db::StorageInterface, services, types::{api::customers, storage}, }; #[instrument(skip(db))] pub async fn create_customer( - db: &dyn Db, + db: &dyn StorageInterface, merchant_account: storage::MerchantAccount, customer_data: customers::CreateCustomerRequest, ) -> RouterResponse { @@ -34,7 +34,7 @@ pub async fn create_customer( #[instrument(skip(db))] pub async fn retrieve_customer( - db: &dyn Db, + db: &dyn StorageInterface, merchant_account: storage::MerchantAccount, req: customers::CustomerId, ) -> RouterResponse { @@ -48,7 +48,7 @@ pub async fn retrieve_customer( #[instrument(skip(db))] pub async fn delete_customer( - db: &dyn Db, + db: &dyn StorageInterface, merchant_account: storage::MerchantAccount, req: customers::CustomerId, ) -> RouterResponse { @@ -65,7 +65,7 @@ pub async fn delete_customer( #[instrument(skip(db))] pub async fn update_customer( - db: &dyn Db, + db: &dyn StorageInterface, merchant_account: storage::MerchantAccount, update_customer: customers::CustomerUpdateRequest, ) -> RouterResponse { diff --git a/crates/router/src/core/errors.rs b/crates/router/src/core/errors.rs index 81cdee3b24..b6475cb4c7 100644 --- a/crates/router/src/core/errors.rs +++ b/crates/router/src/core/errors.rs @@ -25,10 +25,11 @@ macro_rules! impl_error_display { ($st: ident, $arg: tt) => { impl std::fmt::Display for $st { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - fmt.write_str(&format!( + write!( + fmt, "{{ error_type: {:?}, error_description: {} }}", self, $arg - )) + ) } } }; diff --git a/crates/router/src/core/mandate.rs b/crates/router/src/core/mandate.rs index b5822adebf..d784d9c43e 100644 --- a/crates/router/src/core/mandate.rs +++ b/crates/router/src/core/mandate.rs @@ -3,7 +3,7 @@ use router_env::{tracing, tracing::instrument}; use crate::{ core::errors::{self, RouterResponse, StorageErrorExt}, - db::{mandate::IMandate, Db}, + db::StorageInterface, routes::AppState, services, types::{ @@ -30,7 +30,7 @@ pub async fn get_mandate( #[instrument(skip(db))] pub async fn revoke_mandate( - db: &dyn Db, + db: &dyn StorageInterface, merchant_account: storage::MerchantAccount, req: mandates::MandateId, ) -> RouterResponse { diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index e7c81ef126..e8a41aabeb 100644 --- a/crates/router/src/core/payment_methods/cards.rs +++ b/crates/router/src/core/payment_methods/cards.rs @@ -11,9 +11,7 @@ use crate::{ errors::{self, CustomResult, RouterResponse, RouterResult, StorageErrorExt}, payment_methods::transformers as payment_methods, }, - db::{ - merchant_connector_account::IMerchantConnectorAccount, payment_method::IPaymentMethod, Db, - }, + db::StorageInterface, pii::prelude::*, routes::AppState, services, @@ -26,7 +24,7 @@ use crate::{ #[instrument(skip_all)] pub async fn create_payment_method( - db: &dyn Db, + db: &dyn StorageInterface, req: &api::CreatePaymentMethod, customer_id: String, payment_method_id: String, @@ -63,7 +61,7 @@ pub async fn add_payment_method( .attach_printable("Add Card Failed"), None => { create_payment_method( - &state.store, + &*state.store, &req, customer_id, "payment_method_id".to_owned(), @@ -100,7 +98,7 @@ pub async fn add_card( merchant_id: &str, ) -> CustomResult { let locker = &state.conf.locker; - let db = &state.store; + let db = &*state.store; let request = payment_methods::mk_add_card_request(locker, &card, &customer_id, &req)?; // FIXME use call_api 2. Serde's handle should be inside the generic function let response = if !locker.mock_locker { @@ -138,7 +136,7 @@ pub async fn add_card( #[instrument(skip_all)] pub async fn mock_add_card( - db: &dyn Db, + db: &dyn StorageInterface, card_id: &str, card: &api::CardDetail, ) -> CustomResult { @@ -175,7 +173,7 @@ pub async fn mock_add_card( #[instrument(skip_all)] pub async fn mock_get_card<'a>( - db: &dyn Db, + db: &dyn StorageInterface, card_id: &'a str, ) -> CustomResult { let locker_mock_up = db @@ -227,7 +225,7 @@ pub async fn get_card_from_legacy_locker<'a>( .attach_printable(format!("Got 4xx from the locker: {err:?}"))), }? } else { - mock_get_card(&state.store, card_id) + mock_get_card(&*state.store, card_id) .await .change_context(errors::ApiErrorResponse::InternalServerError)? }; @@ -256,7 +254,7 @@ pub async fn delete_card<'a>( } pub async fn list_payment_methods( - db: &dyn Db, + db: &dyn StorageInterface, merchant_account: storage::MerchantAccount, mut req: api::ListPaymentMethodRequest, ) -> RouterResponse> { @@ -386,7 +384,7 @@ pub async fn list_customer_payment_method( merchant_account: storage::MerchantAccount, customer_id: &str, ) -> RouterResponse { - let db = &state.store; + let db = &*state.store; let all_mcas = db .find_merchant_connector_account_by_merchant_id_list(&merchant_account.merchant_id) .await @@ -509,7 +507,7 @@ impl BasiliskCardSupport { card_exp_year: card_exp_year.into(), card_holder_name: Some(card_holder_name.into()), }; - let db = &state.store; + let db = &*state.store; mock_add_card(db, payment_token, &card_detail) .await .change_context(errors::ApiErrorResponse::InternalServerError) @@ -595,7 +593,7 @@ pub async fn retrieve_payment_method( state: &AppState, pm: api::PaymentMethodId, ) -> RouterResponse { - let db = &state.store; + let db = &*state.store; let pm = db .find_payment_method(&pm.payment_method_id) .await diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 4a5848f28b..49d319eb08 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -25,7 +25,7 @@ use crate::{ payments, payments::transformers as payments_transformers, }, - db::Db, + db::StorageInterface, pii::Email, routes::AppState, scheduler::utils as pt_utils, @@ -87,7 +87,7 @@ where let (operation, customer) = operation .to_domain()? .get_or_create_customer_details( - &state.store, + &*state.store, &mut payment_data, customer_details, merchant_id, @@ -110,7 +110,7 @@ where let (operation, mut payment_data) = operation .to_update_tracker()? - .update_trackers(&state.store, &payment_id, payment_data, customer.clone()) + .update_trackers(&*state.store, &payment_id, payment_data, customer.clone()) .await?; operation @@ -290,7 +290,7 @@ where // To perform router related operation for PaymentResponse PaymentResponse: Operation, { - let db = &state.store; + let db = &*state.store; let stime_connector = Instant::now(); @@ -454,7 +454,7 @@ pub fn should_call_connector( } pub async fn list_payments( - db: &dyn Db, + db: &dyn StorageInterface, merchant: storage::MerchantAccount, constraints: api::PaymentListConstraints, ) -> RouterResponse { @@ -476,7 +476,7 @@ pub async fn list_payments( } pub async fn add_process_sync_task( - db: &dyn Db, + db: &dyn StorageInterface, payment_attempt: &storage::PaymentAttempt, schedule_time: time::PrimitiveDateTime, ) -> Result<(), errors::ProcessTrackerError> { diff --git a/crates/router/src/core/payments/flows/authorize_flow.rs b/crates/router/src/core/payments/flows/authorize_flow.rs index 24b3a02c52..3c91ca524e 100644 --- a/crates/router/src/core/payments/flows/authorize_flow.rs +++ b/crates/router/src/core/payments/flows/authorize_flow.rs @@ -9,7 +9,6 @@ use crate::{ errors::{self, ConnectorErrorExt, RouterResult, StorageErrorExt}, payments::{self, helpers, transformers, PaymentData}, }, - db::mandate::IMandate, routes::AppState, scheduler::metrics, services, diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index 1251f05e4a..f4383bb2ac 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -16,7 +16,7 @@ use crate::{ errors::{self, CustomResult, RouterResult, StorageErrorExt}, payment_methods::cards, }, - db::{mandate::IMandate, payment_method::IPaymentMethod, temp_card::ITempCard, Db}, + db::StorageInterface, routes::AppState, services, types::{ @@ -31,7 +31,7 @@ use crate::{ }; pub async fn get_address_for_payment_request( - db: &dyn Db, + db: &dyn StorageInterface, req_address: Option<&api::Address>, address_id: Option<&str>, ) -> CustomResult, errors::ApiErrorResponse> { @@ -82,7 +82,7 @@ pub async fn get_address_for_payment_request( } pub async fn get_address_by_id( - db: &dyn Db, + db: &dyn StorageInterface, address_id: Option, ) -> CustomResult, errors::ApiErrorResponse> { match address_id { @@ -131,7 +131,7 @@ pub async fn get_token_for_recurring_mandate( req: &api::PaymentsRequest, merchant_id: &str, ) -> RouterResult<(Option, Option)> { - let db = &state.store; + let db = &*state.store; let mandate_id = req.mandate_id.clone().get_required_value("mandate_id")?; let mandate = db @@ -502,7 +502,7 @@ pub(crate) fn client_secret_auth( } pub async fn get_customer_from_details( - db: &dyn Db, + db: &dyn StorageInterface, customer_id: Option, merchant_id: &str, ) -> CustomResult, errors::StorageError> { @@ -518,7 +518,7 @@ pub async fn get_customer_from_details( #[instrument(skip_all)] pub async fn create_customer_if_not_exist<'a, F: Clone, R>( operation: BoxedOperation<'a, F, R>, - db: &dyn Db, + db: &dyn StorageInterface, payment_data: &mut PaymentData, req: Option, merchant_id: &str, @@ -616,7 +616,7 @@ impl Vault { state: &AppState, lookup_key: &str, ) -> RouterResult> { - let resp = cards::mock_get_card(&state.store, lookup_key) + let resp = cards::mock_get_card(&*state.store, lookup_key) .await .change_context(errors::ApiErrorResponse::InternalServerError)?; let card = resp.card; @@ -655,7 +655,7 @@ impl Vault { card_exp_year: card.card_exp_year.clone(), card_holder_name: Some(card.card_holder_name.clone()), }; - let db = &state.store; + let db = &*state.store; cards::mock_add_card(db, txn_id, &card_detail) .await .change_context(errors::ApiErrorResponse::InternalServerError) @@ -813,7 +813,7 @@ where } pub(super) async fn filter_by_constraints( - db: &dyn Db, + db: &dyn StorageInterface, constraints: &api::PaymentListConstraints, merchant_id: &str, ) -> CustomResult, errors::StorageError> { diff --git a/crates/router/src/core/payments/operations.rs b/crates/router/src/core/payments/operations.rs index 58aea89831..4d73ed45ab 100644 --- a/crates/router/src/core/payments/operations.rs +++ b/crates/router/src/core/payments/operations.rs @@ -7,7 +7,6 @@ mod payment_session; mod payment_start; mod payment_status; mod payment_update; - use async_trait::async_trait; use error_stack::{report, IntoReport, ResultExt}; pub use payment_cancel::PaymentCancel; @@ -25,7 +24,7 @@ use storage::Customer; use super::{helpers, CustomerDetails, PaymentData}; use crate::{ core::errors::{self, CustomResult, RouterResult}, - db::Db, + db::StorageInterface, routes::AppState, scheduler::{metrics, workflows::payment_sync}, types::{ @@ -100,7 +99,7 @@ pub trait Domain: Send + Sync { /// This will fetch customer details, (this operation is flow specific) async fn get_or_create_customer_details<'a>( &'a self, - db: &dyn Db, + db: &dyn StorageInterface, payment_data: &mut PaymentData, request: Option, merchant_id: &str, @@ -130,7 +129,7 @@ pub trait Domain: Send + Sync { pub trait UpdateTracker: Send { async fn update_trackers<'b>( &'b self, - db: &dyn Db, + db: &dyn StorageInterface, payment_id: &api::PaymentIdType, payment_data: D, customer: Option, @@ -143,7 +142,7 @@ pub trait UpdateTracker: Send { pub trait PostUpdateTracker: Send { async fn update_tracker<'b>( &'b self, - db: &dyn Db, + db: &dyn StorageInterface, payment_id: &api::PaymentIdType, payment_data: D, response: Option>, @@ -161,7 +160,7 @@ where #[instrument(skip_all)] async fn get_or_create_customer_details<'a>( &'a self, - db: &dyn Db, + db: &dyn StorageInterface, payment_data: &mut PaymentData, request: Option, merchant_id: &str, @@ -217,9 +216,9 @@ where metrics::TASKS_ADDED_COUNT.add(&metrics::CONTEXT, 1, &[]); // Metrics let schedule_time = payment_sync::get_sync_process_schedule_time( + &*state.store, &payment_attempt.connector, &payment_attempt.merchant_id, - state.store.redis_conn.clone(), 0, ) .await @@ -227,7 +226,7 @@ where .change_context(errors::ApiErrorResponse::InternalServerError)?; match schedule_time { - Some(stime) => super::add_process_sync_task(&state.store, payment_attempt, stime) + Some(stime) => super::add_process_sync_task(&*state.store, payment_attempt, stime) .await .into_report() .change_context(errors::ApiErrorResponse::InternalServerError), @@ -248,7 +247,7 @@ where #[instrument(skip_all)] async fn get_or_create_customer_details<'a>( &'a self, - db: &dyn Db, + db: &dyn StorageInterface, payment_data: &mut PaymentData, _request: Option, merchant_id: &str, @@ -305,7 +304,7 @@ where #[instrument(skip_all)] async fn get_or_create_customer_details<'a>( &'a self, - db: &dyn Db, + db: &dyn StorageInterface, payment_data: &mut PaymentData, _request: Option, merchant_id: &str, @@ -352,7 +351,7 @@ where #[instrument(skip_all)] async fn get_or_create_customer_details<'a>( &'a self, - db: &dyn Db, + db: &dyn StorageInterface, payment_data: &mut PaymentData, _request: Option, merchant_id: &str, diff --git a/crates/router/src/core/payments/operations/payment_cancel.rs b/crates/router/src/core/payments/operations/payment_cancel.rs index c26d7675fe..efe2ee53d9 100644 --- a/crates/router/src/core/payments/operations/payment_cancel.rs +++ b/crates/router/src/core/payments/operations/payment_cancel.rs @@ -11,10 +11,7 @@ use crate::{ errors::{self, RouterResult, StorageErrorExt}, payments::{CustomerDetails, PaymentAddress, PaymentData}, }, - db::{ - connector_response::IConnectorResponse, payment_attempt::IPaymentAttempt, - payment_intent::IPaymentIntent, Db, - }, + db::StorageInterface, routes::AppState, types::{ api, @@ -44,7 +41,7 @@ impl GetTracker, api::PaymentsCancelRequest> PaymentData, Option, )> { - let db = &state.store; + let db = &*state.store; let payment_id = payment_id .get_payment_intent_id() .change_context(errors::ApiErrorResponse::PaymentNotFound)?; @@ -115,7 +112,7 @@ impl UpdateTracker, api::PaymentsCancelRequest> for #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - db: &dyn Db, + db: &dyn StorageInterface, _payment_id: &api::PaymentIdType, mut payment_data: PaymentData, _customer: Option, diff --git a/crates/router/src/core/payments/operations/payment_capture.rs b/crates/router/src/core/payments/operations/payment_capture.rs index c4a4cfd038..375e603ef8 100644 --- a/crates/router/src/core/payments/operations/payment_capture.rs +++ b/crates/router/src/core/payments/operations/payment_capture.rs @@ -10,10 +10,7 @@ use crate::{ errors::{self, RouterResult, StorageErrorExt}, payments::{self, helpers}, }, - db::{ - connector_response::IConnectorResponse, payment_attempt::IPaymentAttempt, - payment_intent::IPaymentIntent, Db, - }, + db::StorageInterface, routes::AppState, types::{api, api::PaymentsCaptureRequest, storage, Connector}, utils::OptionExt, @@ -41,7 +38,7 @@ impl GetTracker, api::PaymentsCaptu payments::PaymentData, Option, )> { - let db = &state.store; + let db = &*state.store; let (payment_intent, mut payment_attempt, currency, amount); let payment_id = payment_id @@ -139,7 +136,7 @@ impl UpdateTracker, api::PaymentsCaptureRe #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - _db: &dyn Db, + _db: &dyn StorageInterface, _payment_id: &api::PaymentIdType, payment_data: payments::PaymentData, _customer: Option, diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index 340eaad9ba..aeffeaee59 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -12,10 +12,7 @@ use crate::{ payments::{helpers, CustomerDetails, PaymentAddress, PaymentData}, utils as core_utils, }, - db::{ - connector_response::IConnectorResponse, payment_attempt::IPaymentAttempt, - payment_intent::IPaymentIntent, Db, - }, + db::StorageInterface, routes::AppState, types::{ self, api, @@ -45,7 +42,7 @@ impl GetTracker, api::PaymentsRequest> for Pa PaymentData, Option, )> { - let db = &state.store; + let db = &*state.store; let (mut payment_intent, mut payment_attempt, currency, amount, connector_response); let payment_id = payment_id @@ -164,7 +161,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - db: &dyn Db, + db: &dyn StorageInterface, _payment_id: &api::PaymentIdType, mut payment_data: PaymentData, _customer: Option, diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 3bc978931d..8959bcdb3f 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -14,10 +14,7 @@ use crate::{ payments::{self, helpers, CustomerDetails, PaymentAddress, PaymentData}, utils as core_utils, }, - db::{ - connector_response::IConnectorResponse, payment_attempt::IPaymentAttempt, - payment_intent::IPaymentIntent, Db, - }, + db::StorageInterface, routes::AppState, types::{ self, api, @@ -26,7 +23,7 @@ use crate::{ enums::{self, IntentStatus}, }, }, - utils::{self, OptionExt}, + utils::OptionExt, }; #[derive(Debug, Clone, Copy, PaymentOperation)] #[operation(ops = "all", flow = "authorize")] @@ -48,7 +45,7 @@ impl GetTracker, api::PaymentsRequest> for Pa PaymentData, Option, )> { - let db = &state.store; + let db = &*state.store; let (payment_intent, payment_attempt, connector_response); @@ -73,7 +70,9 @@ impl GetTracker, api::PaymentsRequest> for Pa let browser_info = request .browser_info .clone() - .map(|x| utils::Encode::::encode_to_value(&x)) + .map(|x| { + common_utils::ext_traits::Encode::::encode_to_value(&x) + }) .transpose() .change_context(errors::ApiErrorResponse::InvalidDataValue { field_name: "browser_info", @@ -154,6 +153,7 @@ impl GetTracker, api::PaymentsRequest> for Pa payment_intent.status, self, ); + Ok(( operation, PaymentData { @@ -191,7 +191,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - db: &dyn Db, + db: &dyn StorageInterface, _payment_id: &api::PaymentIdType, mut payment_data: PaymentData, _customer: Option, diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index a982ee5574..97a4ff98b0 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -8,7 +8,7 @@ use crate::{ errors::{self, RouterResult, StorageErrorExt}, payments::PaymentData, }, - db::Db, + db::StorageInterface, services::RedirectForm, types::{ self, api, @@ -30,7 +30,7 @@ impl PostUpdateTracker, types::PaymentsAuthorizeData { async fn update_tracker<'b>( &'b self, - db: &dyn Db, + db: &dyn StorageInterface, payment_id: &api::PaymentIdType, mut payment_data: PaymentData, response: Option< @@ -52,7 +52,7 @@ impl PostUpdateTracker, types::PaymentsAuthorizeData impl PostUpdateTracker, types::PaymentsSyncData> for PaymentResponse { async fn update_tracker<'b>( &'b self, - db: &dyn Db, + db: &dyn StorageInterface, payment_id: &api::PaymentIdType, payment_data: PaymentData, response: Option< @@ -72,7 +72,7 @@ impl PostUpdateTracker, types::PaymentsCaptureData> { async fn update_tracker<'b>( &'b self, - db: &dyn Db, + db: &dyn StorageInterface, payment_id: &api::PaymentIdType, payment_data: PaymentData, response: Option< @@ -90,7 +90,7 @@ impl PostUpdateTracker, types::PaymentsCaptureData> impl PostUpdateTracker, types::PaymentsCancelData> for PaymentResponse { async fn update_tracker<'b>( &'b self, - db: &dyn Db, + db: &dyn StorageInterface, payment_id: &api::PaymentIdType, payment_data: PaymentData, response: Option< @@ -105,7 +105,7 @@ impl PostUpdateTracker, types::PaymentsCancelData> f } async fn payment_response_ut( - db: &dyn Db, + db: &dyn StorageInterface, _payment_id: &api::PaymentIdType, mut payment_data: PaymentData, response: Option>, diff --git a/crates/router/src/core/payments/operations/payment_session.rs b/crates/router/src/core/payments/operations/payment_session.rs index ebdfc92744..da6964fa2b 100644 --- a/crates/router/src/core/payments/operations/payment_session.rs +++ b/crates/router/src/core/payments/operations/payment_session.rs @@ -11,7 +11,7 @@ use crate::{ errors::{self, RouterResult, StorageErrorExt}, payments::{self, helpers, PaymentData}, }, - db::{payment_attempt::IPaymentAttempt, payment_intent::IPaymentIntent, Db}, + db::StorageInterface, routes::AppState, types::{ api, @@ -47,7 +47,7 @@ impl GetTracker, api::PaymentsSessionRequest> .get_payment_intent_id() .change_context(errors::ApiErrorResponse::PaymentNotFound)?; - let db = &state.store; + let db = &*state.store; let mut payment_attempt = db .find_payment_attempt_by_payment_id_merchant_id(&payment_id, merchant_id) @@ -91,7 +91,7 @@ impl GetTracker, api::PaymentsSessionRequest> payment_intent.shipping_address_id = shipping_address.clone().map(|x| x.address_id); payment_intent.billing_address_id = billing_address.clone().map(|x| x.address_id); - let db = db as &dyn Db; + let db = db as &dyn StorageInterface; let connector_response = db .find_connector_response_by_payment_id_merchant_id_txn_id( &payment_intent.payment_id, @@ -136,7 +136,7 @@ impl UpdateTracker, api::PaymentsSessionRequest> for #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - _db: &dyn Db, + _db: &dyn StorageInterface, _payment_id: &api::PaymentIdType, payment_data: PaymentData, _customer: Option, @@ -187,7 +187,7 @@ where #[instrument(skip_all)] async fn get_or_create_customer_details<'a>( &'a self, - db: &dyn Db, + db: &dyn StorageInterface, payment_data: &mut PaymentData, request: Option, merchant_id: &str, diff --git a/crates/router/src/core/payments/operations/payment_start.rs b/crates/router/src/core/payments/operations/payment_start.rs index 0c8189f543..d2af2bc7e5 100644 --- a/crates/router/src/core/payments/operations/payment_start.rs +++ b/crates/router/src/core/payments/operations/payment_start.rs @@ -11,7 +11,7 @@ use crate::{ errors::{self, CustomResult, RouterResult, StorageErrorExt}, payments::{helpers, CustomerDetails, PaymentAddress, PaymentData}, }, - db::Db, + db::StorageInterface, routes::AppState, types::{ api, @@ -42,7 +42,7 @@ impl GetTracker, api::PaymentsStartRequest> f Option, )> { let (mut payment_intent, payment_attempt, currency, amount); - let db = &state.store as &dyn Db; + let db = &*state.store; let payment_id = payment_id .get_payment_intent_id() @@ -141,7 +141,7 @@ impl UpdateTracker, api::PaymentsStartRequest> for P #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - _db: &dyn Db, + _db: &dyn StorageInterface, _payment_id: &api::PaymentIdType, payment_data: PaymentData, _customer: Option, @@ -195,7 +195,7 @@ where #[instrument(skip_all)] async fn get_or_create_customer_details<'a>( &'a self, - db: &dyn Db, + db: &dyn StorageInterface, payment_data: &mut PaymentData, request: Option, merchant_id: &str, diff --git a/crates/router/src/core/payments/operations/payment_status.rs b/crates/router/src/core/payments/operations/payment_status.rs index 263a6e82b5..cdb9ef3638 100644 --- a/crates/router/src/core/payments/operations/payment_status.rs +++ b/crates/router/src/core/payments/operations/payment_status.rs @@ -11,7 +11,7 @@ use crate::{ errors::{self, ApiErrorResponse, RouterResult, StorageErrorExt}, payments::{helpers, CustomerDetails, PaymentAddress, PaymentData}, }, - db::Db, + db::StorageInterface, routes::AppState, types::{api, storage, Connector}, utils::{self, OptionExt}, @@ -47,7 +47,7 @@ impl Operation for &PaymentStatus { impl UpdateTracker, api::PaymentsRequest> for PaymentStatus { async fn update_trackers<'b>( &'b self, - _db: &dyn Db, + _db: &dyn StorageInterface, _payment_id: &api::PaymentIdType, payment_data: PaymentData, _customer: Option, @@ -63,7 +63,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen impl UpdateTracker, api::PaymentsRetrieveRequest> for PaymentStatus { async fn update_trackers<'b>( &'b self, - _db: &dyn Db, + _db: &dyn StorageInterface, _payment_id: &api::PaymentIdType, payment_data: PaymentData, _customer: Option, @@ -96,7 +96,7 @@ impl GetTracker, api::PaymentsRetrieveRequest PaymentData, Option, )> { - get_tracker_for_sync(payment_id, merchant_id, &state.store, request, self).await + get_tracker_for_sync(payment_id, merchant_id, &*state.store, request, self).await } } @@ -107,7 +107,7 @@ async fn get_tracker_for_sync< >( payment_id: &api::PaymentIdType, merchant_id: &str, - db: &dyn Db, + db: &dyn StorageInterface, request: &api::PaymentsRetrieveRequest, operation: Op, ) -> RouterResult<( diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index 0bec08e812..fb31bfcc1f 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -12,7 +12,7 @@ use crate::{ payments::{self, helpers, CustomerDetails, PaymentAddress, PaymentData}, utils as core_utils, }, - db::{payment_attempt::IPaymentAttempt, payment_intent::IPaymentIntent, Db}, + db::StorageInterface, routes::AppState, types::{ api, @@ -52,7 +52,7 @@ impl GetTracker, api::PaymentsRequest> for Pa .get_payment_intent_id() .change_context(errors::ApiErrorResponse::PaymentNotFound)?; - let db = &state.store; + let db = &*state.store; let (token, payment_method_type, setup_mandate) = helpers::get_token_pm_type_mandate_details(state, request, mandate_type, merchant_id) .await?; @@ -108,7 +108,7 @@ impl GetTracker, api::PaymentsRequest> for Pa payment_intent.shipping_address_id = shipping_address.clone().map(|x| x.address_id); payment_intent.billing_address_id = billing_address.clone().map(|x| x.address_id); - let db = db as &dyn Db; + let db = db as &dyn StorageInterface; let connector_response = db .find_connector_response_by_payment_id_merchant_id_txn_id( &payment_intent.payment_id, @@ -171,7 +171,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - db: &dyn Db, + db: &dyn StorageInterface, _payment_id: &api::PaymentIdType, mut payment_data: PaymentData, customer: Option, @@ -181,7 +181,6 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen { let is_payment_method_unavailable = payment_data.payment_attempt.payment_method_id.is_none() - && payment_data.payment_method_data.is_none() && payment_data.payment_intent.status == enums::IntentStatus::RequiresPaymentMethod; let payment_method = payment_data.payment_attempt.payment_method; diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index d54ce4f118..7e98dd588b 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -10,7 +10,6 @@ use crate::{ errors::{self, RouterResponse, RouterResult, StorageErrorExt}, payments::{self, helpers}, }, - db::Db, routes::AppState, services::{self, RedirectForm}, types::{ @@ -41,7 +40,7 @@ where //TODO: everytime parsing the json may have impact? let (merchant_connector_account, payment_method, router_data); - let db = &state.store as &dyn Db; + let db = &*state.store; merchant_connector_account = db .find_merchant_connector_account_by_merchant_id_connector( &merchant_account.merchant_id, diff --git a/crates/router/src/core/refunds.rs b/crates/router/src/core/refunds.rs index dd45ce3443..dddb5079f4 100644 --- a/crates/router/src/core/refunds.rs +++ b/crates/router/src/core/refunds.rs @@ -9,10 +9,7 @@ use crate::{ errors::{self, ConnectorErrorExt, RouterResponse, RouterResult, StorageErrorExt}, payments, utils as core_utils, }, - db::{ - merchant_account::IMerchantAccount, payment_attempt::IPaymentAttempt, - payment_intent::IPaymentIntent, process_tracker::IProcessTracker, refund::IRefund, Db, - }, + db::StorageInterface, logger, routes::AppState, services, @@ -32,7 +29,7 @@ pub async fn refund_create_core( merchant_account: storage::merchant_account::MerchantAccount, req: refunds::RefundRequest, ) -> RouterResponse { - let db = &state.store; + let db = &*state.store; let (merchant_id, payment_intent, payment_attempt, amount); merchant_id = &merchant_account.merchant_id; @@ -159,7 +156,7 @@ pub async fn refund_retrieve_core( merchant_account: storage::MerchantAccount, refund_id: String, ) -> RouterResponse { - let db = &state.store; + let db = &*state.store; let (merchant_id, payment_intent, payment_attempt, refund, response); merchant_id = &merchant_account.merchant_id; @@ -263,7 +260,7 @@ pub async fn sync_refund_with_gateway( // ********************************************** REFUND UPDATE ********************************************** pub async fn refund_update_core( - db: &dyn Db, + db: &dyn StorageInterface, merchant_account: storage::MerchantAccount, refund_id: &str, req: refunds::RefundRequest, @@ -297,7 +294,7 @@ pub async fn validate_and_create_refund( refund_amount: i32, req: refunds::RefundRequest, ) -> RouterResult { - let db = &state.store; + let db = &*state.store; let (refund_id, all_refunds, currency, refund_create_req, refund); // Only for initial dev and testing @@ -484,7 +481,7 @@ pub async fn schedule_refund_execution( payment_intent: &storage::PaymentIntent, ) -> RouterResult { // refunds::RefundResponse> { - let db = &state.store; + let db = &*state.store; let runner = "REFUND_WORKFLOW_ROUTER"; let task = "EXECUTE_REFUND"; let task_id = format!("{}_{}_{}", runner, task, refund.internal_reference_id); @@ -538,7 +535,7 @@ pub async fn schedule_refund_execution( #[instrument(skip_all)] pub async fn sync_refund_with_gateway_workflow( - db: &dyn Db, + db: &dyn StorageInterface, refund_tracker: &storage::ProcessTracker, ) -> RouterResult<()> { let refund_core = @@ -572,7 +569,7 @@ pub async fn start_refund_workflow( match refund_tracker.name.as_deref() { Some("EXECUTE_REFUND") => trigger_refund_execute_workflow(state, refund_tracker).await, Some("SYNC_REFUND") => { - sync_refund_with_gateway_workflow(&state.store, refund_tracker).await + sync_refund_with_gateway_workflow(&*state.store, refund_tracker).await } _ => Err(report!(errors::ApiErrorResponse::InternalServerError) .attach_printable("Job name cannot be identified")), @@ -584,7 +581,7 @@ pub async fn trigger_refund_execute_workflow( state: &AppState, refund_tracker: &storage::ProcessTracker, ) -> RouterResult<()> { - let db = &state.store; + let db = &*state.store; let refund_core = serde_json::from_value::(refund_tracker.tracking_data.clone()) .into_report() @@ -668,7 +665,7 @@ pub fn refund_to_refund_core_workflow_model( #[instrument(skip_all)] pub async fn add_refund_sync_task( - db: &dyn Db, + db: &dyn StorageInterface, refund: &storage::Refund, runner: &str, ) -> RouterResult { @@ -703,7 +700,7 @@ pub async fn add_refund_sync_task( #[instrument(skip_all)] pub async fn add_refund_execute_task( - db: &dyn Db, + db: &dyn StorageInterface, refund: &storage::Refund, runner: &str, ) -> RouterResult { diff --git a/crates/router/src/core/refunds/validator.rs b/crates/router/src/core/refunds/validator.rs index edf935a226..586f6b0949 100644 --- a/crates/router/src/core/refunds/validator.rs +++ b/crates/router/src/core/refunds/validator.rs @@ -4,7 +4,7 @@ use time::PrimitiveDateTime; use crate::{ core::errors::{self, CustomResult, RouterResult}, - db::Db, + db::StorageInterface, logger, types::storage::{self, enums}, utils, @@ -91,7 +91,7 @@ pub fn validate_maximum_refund_against_payment_attempt( #[instrument(skip(db))] pub async fn validate_uniqueness_of_refund_id_against_merchant_id( - db: &dyn Db, + db: &dyn StorageInterface, payment_id: &str, merchant_id: &str, refund_id: &str, diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index c4742cad7e..89cf5462b3 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -7,7 +7,6 @@ use super::payments::{helpers, PaymentAddress}; use crate::{ consts, core::errors::{self, RouterResult}, - db::merchant_connector_account::IMerchantConnectorAccount, routes::AppState, types::{ self, api, @@ -28,7 +27,7 @@ pub async fn construct_refund_router_data<'a, F>( payment_attempt: &storage::PaymentAttempt, refund: &'a storage::Refund, ) -> RouterResult> { - let db = &state.store; + let db = &*state.store; //TODO: everytime parsing the json may have impact? let merchant_connector_account = db .find_merchant_connector_account_by_merchant_id_connector( diff --git a/crates/router/src/core/webhooks.rs b/crates/router/src/core/webhooks.rs index ca84df2f58..0c4c78e8ef 100644 --- a/crates/router/src/core/webhooks.rs +++ b/crates/router/src/core/webhooks.rs @@ -11,7 +11,7 @@ use crate::{ errors::{self, CustomResult, RouterResponse}, payments, }, - db::Db, + db::StorageInterface, logger, routes::AppState, services, @@ -99,7 +99,7 @@ async fn create_event_and_trigger_outgoing_webhook( primary_object_id: String, primary_object_type: enums::EventObjectType, content: api::OutgoingWebhookContent, - db: services::Store, + db: Box, ) -> CustomResult<(), errors::WebhooksFlowError> { let arbiter = actix::Arbiter::try_current() .ok_or(errors::WebhooksFlowError::ForkFlowFailed) @@ -115,7 +115,7 @@ async fn create_event_and_trigger_outgoing_webhook( primary_object_type, }; - let event = (&db as &dyn Db) + let event = db .insert_event(new_event) .await .change_context(errors::WebhooksFlowError::WebhookEventCreationFailed)?; @@ -128,7 +128,7 @@ async fn create_event_and_trigger_outgoing_webhook( timestamp: event.created_at, }; - arbiter.spawn(async { + arbiter.spawn(async move { let result = trigger_webhook_to_merchant(merchant_account, outgoing_webhook, db).await; if let Err(e) = result { @@ -142,7 +142,7 @@ async fn create_event_and_trigger_outgoing_webhook( async fn trigger_webhook_to_merchant( merchant_account: storage::MerchantAccount, webhook: api::OutgoingWebhook, - _db: services::Store, + _db: Box, ) -> CustomResult<(), errors::WebhooksFlowError> { let webhook_details_json = merchant_account .webhook_details @@ -205,10 +205,10 @@ pub async fn webhooks_core( let source_verified = connector .verify_webhook_source( + &*state.store, req.headers(), &body, &merchant_account.merchant_id, - state.store.redis_conn.clone(), ) .await .change_context(errors::ApiErrorResponse::InternalServerError) @@ -216,10 +216,10 @@ pub async fn webhooks_core( let decoded_body = connector .decode_webhook_body( + &*state.store, req.headers(), &body, &merchant_account.merchant_id, - state.store.redis_conn.clone(), ) .await .change_context(errors::ApiErrorResponse::InternalServerError) @@ -231,10 +231,10 @@ pub async fn webhooks_core( .attach_printable("Could not find event type in incoming webhook body")?; let process_webhook_further = utils::lookup_webhook_event( + &*state.store, connector_name, &merchant_account.merchant_id, &event_type, - state.store.redis_conn.clone(), ) .await; diff --git a/crates/router/src/core/webhooks/utils.rs b/crates/router/src/core/webhooks/utils.rs index 9b775a6f27..55d46393ba 100644 --- a/crates/router/src/core/webhooks/utils.rs +++ b/crates/router/src/core/webhooks/utils.rs @@ -1,21 +1,24 @@ -use crate::{connection::RedisPool, types::api}; +use crate::{ + db::{get_and_deserialize_key, StorageInterface}, + types::api, +}; fn default_webhook_config() -> api::MerchantWebhookConfig { std::collections::HashSet::from([api::IncomingWebhookEvent::PaymentIntentSuccess]) } pub async fn lookup_webhook_event( + db: &dyn StorageInterface, connector_id: &str, merchant_id: &str, event: &api::IncomingWebhookEvent, - conn: RedisPool, ) -> bool { let redis_key = format!("whconf_{}_{}", merchant_id, connector_id); - let webhook_config: api::MerchantWebhookConfig = conn - .get_and_deserialize_key(&redis_key, "MerchantWebhookConfig") - .await - .map(|h| &h | &default_webhook_config()) - .unwrap_or_else(|_| default_webhook_config()); + let webhook_config: api::MerchantWebhookConfig = + get_and_deserialize_key(db, &redis_key, "MerchantWebhookConfig") + .await + .map(|h| &h | &default_webhook_config()) + .unwrap_or_else(|_| default_webhook_config()); webhook_config.contains(event) } diff --git a/crates/router/src/db.rs b/crates/router/src/db.rs index 66219c88c3..e2c515e90d 100644 --- a/crates/router/src/db.rs +++ b/crates/router/src/db.rs @@ -1,9 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_variables)] -#![allow(clippy::unwrap_used)] - -// use std::sync::{Arc, Mutex}; - pub mod address; pub mod configs; pub mod connector_response; @@ -17,256 +11,151 @@ pub mod payment_attempt; pub mod payment_intent; pub mod payment_method; pub mod process_tracker; +pub mod queue; pub mod refund; pub mod temp_card; -use dyn_clone::DynClone; +use std::sync::Arc; + +use futures_locks::Mutex; use crate::{ configs::settings::Database, - connection::{make_pg_pool, PgPool}, + connection::{diesel_make_pg_pool, PgPool as PgPoolDiesel}, services::Store, + types::storage::{ + ConnectorResponse, Customer, MerchantAccount, MerchantConnectorAccount, PaymentAttempt, + PaymentIntent, ProcessTracker, Refund, TempCard, + }, }; +#[derive(PartialEq, Eq)] +pub enum StorageImpl { + DieselPostgresql, + DieselPostgresqlTest, + Mock, +} + #[async_trait::async_trait] -pub trait Db: +pub trait StorageInterface: Send + Sync - + DynClone - + payment_attempt::IPaymentAttempt - + mandate::IMandate - + address::IAddress - + configs::IConfig - + temp_card::ITempCard - + customers::ICustomer - + events::IEvent - + merchant_account::IMerchantAccount - + merchant_connector_account::IMerchantConnectorAccount - + locker_mock_up::ILockerMockUp - + payment_intent::IPaymentIntent - + payment_method::IPaymentMethod - + process_tracker::IProcessTracker - + refund::IRefund - + connector_response::IConnectorResponse + + dyn_clone::DynClone + + payment_attempt::PaymentAttemptInterface + + mandate::MandateInterface + + address::AddressInterface + + configs::ConfigInterface + + temp_card::TempCardInterface + + customers::CustomerInterface + + events::EventInterface + + merchant_account::MerchantAccountInterface + + merchant_connector_account::MerchantConnectorAccountInterface + + locker_mock_up::LockerMockUpInterface + + payment_intent::PaymentIntentInterface + + payment_method::PaymentMethodInterface + + process_tracker::ProcessTrackerInterface + + refund::RefundInterface + + queue::QueueInterface + + connector_response::ConnectorResponseInterface + 'static { + async fn close(&mut self) {} } #[derive(Clone)] pub struct SqlDb { - pub conn: PgPool, + pub conn: PgPoolDiesel, } impl SqlDb { pub async fn new(database: &Database) -> Self { Self { - conn: make_pg_pool(database, false).await, + conn: diesel_make_pg_pool(database, false).await, } } pub async fn test(database: &Database) -> Self { Self { - conn: make_pg_pool(database, true).await, + conn: diesel_make_pg_pool( + &Database { + dbname: String::from("test_db"), + ..database.clone() + }, + true, + ) + .await, } } } #[async_trait::async_trait] -impl Db for Store {} +impl StorageInterface for Store { + #[allow(clippy::expect_used)] + async fn close(&mut self) { + std::sync::Arc::get_mut(&mut self.redis_conn) + .expect("Redis connection pool cannot be closed") + .close_connections() + .await; + } +} -// #[derive(Clone, Default)] -// pub struct InMemoryDb { -// payments: Arc>>, -// mandates: Arc>>, -// customers: Arc>>, -// } +#[derive(Clone)] +pub struct MockDb { + merchant_accounts: Arc>>, + merchant_connector_accounts: Arc>>, + payment_attempts: Arc>>, + payment_intents: Arc>>, + customers: Arc>>, + temp_cards: Arc>>, + refunds: Arc>>, + processes: Arc>>, + connector_response: Arc>>, + redis: Arc, +} -// #[async_trait::async_trait] -// impl Db for InMemoryDb { -// async fn find_optional_by_customer_id_merchant_id( -// &self, -// customer_id: &str, -// merchant_id: &str, -// ) -> CustomResult, errors::StorageError> { -// todo!() -// } +impl MockDb { + pub async fn new(redis: &crate::configs::settings::Settings) -> Self { + Self { + merchant_accounts: Default::default(), + merchant_connector_accounts: Default::default(), + payment_attempts: Default::default(), + payment_intents: Default::default(), + customers: Default::default(), + temp_cards: Default::default(), + refunds: Default::default(), + processes: Default::default(), + connector_response: Default::default(), + redis: Arc::new(crate::connection::redis_connection(redis).await), + } + } +} -// #[allow(clippy::unwrap_used)] -// async fn insert_payment_attempt( -// &self, -// payment_attempt: PaymentAttemptNew, -// ) -> CustomResult { -// let mut payments = self.payments.lock().unwrap(); -// let id = payments.len() as i32; +#[async_trait::async_trait] +impl StorageInterface for MockDb { + #[allow(clippy::expect_used)] + async fn close(&mut self) { + std::sync::Arc::get_mut(&mut self.redis) + .expect("Redis connection pool cannot be closed") + .close_connections() + .await; + } +} -// let payment = PaymentAttempt { -// id, -// payment_id: payment_attempt.payment_id, -// merchant_id: payment_attempt.merchant_id, -// txn_id: payment_attempt.txn_id, -// status: payment_attempt.status, -// amount: payment_attempt.amount, -// currency: payment_attempt.currency, -// save_to_locker: payment_attempt.save_to_locker, -// connector: payment_attempt.connector, -// error_message: payment_attempt.error_message, -// offer_amount: payment_attempt.offer_amount, -// surcharge_amount: payment_attempt.surcharge_amount, -// tax_amount: payment_attempt.tax_amount, -// payment_method_id: payment_attempt.payment_method_id, -// payment_method: payment_attempt.payment_method, -// payment_flow: payment_attempt.payment_flow, -// redirect: payment_attempt.redirect, -// connector_transaction_id: payment_attempt.connector_transaction_id, -// capture_method: payment_attempt.capture_method, -// capture_on: payment_attempt.capture_on, -// confirm: payment_attempt.confirm, -// authentication_type: payment_attempt.authentication_type, -// created_at: payment_attempt.created_at.unwrap(), -// modified_at: payment_attempt.modified_at.unwrap(), -// last_synced: payment_attempt.last_synced, -// }; -// payments.push(payment.clone()); -// Ok(payment) -// } +pub async fn get_and_deserialize_key( + db: &dyn StorageInterface, + key: &str, + type_name: &str, +) -> common_utils::errors::CustomResult +where + T: serde::de::DeserializeOwned, +{ + use common_utils::ext_traits::ByteSliceExt; + use error_stack::ResultExt; -// async fn delete_by_customer_id_merchant_id( -// &self, -// customer_id: &str, -// merchant_id: &str, -// ) -> CustomResult { -// todo!() -// } + let bytes = db.get_key(key).await?; + bytes + .parse_struct(type_name) + .change_context(redis_interface::errors::RedisError::JsonDeserializationFailed) +} -// async fn find_by_merchant_id_mandate_id( -// &self, -// merchant_id: &str, -// mandate_id: &str, -// ) -> CustomResult { -// todo!() -// } - -// async fn find_by_merchant_id_customer_id( -// &self, -// merchant_id: &str, -// customer_id: &str, -// ) -> CustomResult, errors::StorageError> { -// todo!() -// } - -// async fn update_by_merchant_id_mandate_id( -// &self, -// merchant_id: &str, -// mandate_id: &str, -// mandate: MandateUpdate, -// ) -> CustomResult { -// todo!() -// } - -// #[allow(clippy::unwrap_used)] -// async fn insert_mandate( -// &self, -// mandate: MandateNew, -// ) -> CustomResult { -// let mut mandates = self.mandates.lock().unwrap(); -// let id = mandates.len() as i32; - -// let mandate = Mandate { -// id, -// mandate_id: mandate.mandate_id, -// customer_id: mandate.customer_id, -// merchant_id: mandate.merchant_id, -// payment_method_id: mandate.payment_method_id, -// mandate_status: mandate.mandate_status, -// mandate_type: mandate.mandate_type, -// customer_accepted_at: mandate.customer_accepted_at, -// customer_ip_address: mandate.customer_ip_address, -// customer_user_agent: mandate.customer_user_agent, -// network_transaction_id: mandate.network_transaction_id, -// previous_transaction_id: mandate.previous_transaction_id, -// created_at: mandate.created_at.unwrap(), -// }; -// mandates.push(mandate.clone()); -// Ok(mandate) -// } - -// async fn update_by_customer_id_merchant_id( -// &self, -// customer_id: String, -// merchant_id: String, -// update: CustomerUpdate, -// ) -> CustomResult { -// let mut customers = self.customers.lock().unwrap(); - -// let mut customer = customers -// .iter_mut() -// .find(|customer| { -// customer.customer_id == customer_id && customer.merchant_id == merchant_id -// }) -// .unwrap(); - -// match update { -// CustomerUpdate::Update { -// name, -// email, -// phone, -// description, -// phone_country_code, -// address, -// metadata, -// } => { -// customer.name = name; -// customer.email = email; -// customer.phone = phone; -// customer.description = description; -// customer.phone_country_code = phone_country_code; -// customer.address = address; -// customer.metadata = metadata; -// } -// } - -// Ok(customer.clone()) -// } - -// async fn find_by_customer_id_merchant_id( -// &self, -// customer_id: &str, -// merchant_id: &str, -// ) -> CustomResult { -// let customers = self.customers.lock().unwrap(); -// let customer = customers -// .iter() -// .find(|customer| { -// customer.merchant_id == merchant_id && customer.customer_id == customer_id -// }) -// .unwrap() -// .clone(); -// Ok(customer) -// } - -// async fn insert_customer( -// &self, -// customer_data: CreateCustomerRequest, -// ) -> CustomResult { -// let mut customers = self.customers.lock().unwrap(); -// let id = customers.len() as i32; - -// let customer = Customer { -// id, -// customer_id: customer_data.customer_id, -// merchant_id: customer_data.merchant_id, -// name: customer_data.name, -// email: customer_data.email, -// phone: customer_data.phone, -// phone_country_code: customer_data.phone_country_code, -// description: customer_data.description, -// address: customer_data.address, -// created_at: crate::utils::date_time::now(), -// metadata: customer_data.metadata, -// }; -// customers.push(customer.clone()); -// Ok(customer) -// } -// } - -dyn_clone::clone_trait_object!(Db); +dyn_clone::clone_trait_object!(StorageInterface); diff --git a/crates/router/src/db/address.rs b/crates/router/src/db/address.rs index ad90307da5..ecdfe89261 100644 --- a/crates/router/src/db/address.rs +++ b/crates/router/src/db/address.rs @@ -1,12 +1,12 @@ +use super::MockDb; use crate::{ connection::pg_connection, core::errors::{self, CustomResult}, - services::Store, types::storage::{Address, AddressNew, AddressUpdate}, }; #[async_trait::async_trait] -pub trait IAddress { +pub trait AddressInterface { async fn update_address( &self, address_id: String, @@ -20,7 +20,7 @@ pub trait IAddress { } #[async_trait::async_trait] -impl IAddress for Store { +impl AddressInterface for super::Store { async fn find_address(&self, address_id: &str) -> CustomResult { let conn = pg_connection(&self.master_pool.conn).await; Address::find_by_address_id(&conn, address_id).await @@ -43,3 +43,25 @@ impl IAddress for Store { address.insert(&conn).await } } + +#[async_trait::async_trait] +impl AddressInterface for MockDb { + async fn find_address(&self, _address_id: &str) -> CustomResult { + todo!() + } + + async fn update_address( + &self, + _address_id: String, + _address: AddressUpdate, + ) -> CustomResult { + todo!() + } + + async fn insert_address( + &self, + _address: AddressNew, + ) -> CustomResult { + todo!() + } +} diff --git a/crates/router/src/db/configs.rs b/crates/router/src/db/configs.rs index e8fd8ea82b..844837e125 100644 --- a/crates/router/src/db/configs.rs +++ b/crates/router/src/db/configs.rs @@ -1,16 +1,14 @@ +use super::MockDb; use crate::{ connection::pg_connection, core::errors::{self, CustomResult}, - services::Store, types::storage::{Config, ConfigNew, ConfigUpdate}, }; #[async_trait::async_trait] -pub trait IConfig { +pub trait ConfigInterface { async fn insert_config(&self, config: ConfigNew) -> CustomResult; - async fn find_config_by_key(&self, key: &str) -> CustomResult; - async fn update_config_by_key( &self, key: &str, @@ -19,7 +17,7 @@ pub trait IConfig { } #[async_trait::async_trait] -impl IConfig for Store { +impl ConfigInterface for super::Store { async fn insert_config(&self, config: ConfigNew) -> CustomResult { let conn = pg_connection(&self.master_pool.conn).await; config.insert(&conn).await @@ -39,3 +37,25 @@ impl IConfig for Store { Config::update_by_key(&conn, key, config_update).await } } + +#[async_trait::async_trait] +impl ConfigInterface for MockDb { + async fn insert_config( + &self, + _config: ConfigNew, + ) -> CustomResult { + todo!() + } + + async fn find_config_by_key(&self, _key: &str) -> CustomResult { + todo!() + } + + async fn update_config_by_key( + &self, + _key: &str, + _config_update: ConfigUpdate, + ) -> CustomResult { + todo!() + } +} diff --git a/crates/router/src/db/connector_response.rs b/crates/router/src/db/connector_response.rs index 89979dd55d..83fdd39d8a 100644 --- a/crates/router/src/db/connector_response.rs +++ b/crates/router/src/db/connector_response.rs @@ -1,12 +1,12 @@ +use super::MockDb; use crate::{ connection::pg_connection, core::errors::{self, CustomResult}, - services::Store, types::storage::{ConnectorResponse, ConnectorResponseNew, ConnectorResponseUpdate}, }; #[async_trait::async_trait] -pub trait IConnectorResponse { +pub trait ConnectorResponseInterface { async fn insert_connector_response( &self, connector_response: ConnectorResponseNew, @@ -25,7 +25,7 @@ pub trait IConnectorResponse { } #[async_trait::async_trait] -impl IConnectorResponse for Store { +impl ConnectorResponseInterface for super::Store { async fn insert_connector_response( &self, connector_response: ConnectorResponseNew, @@ -59,3 +59,50 @@ impl IConnectorResponse for Store { this.update(&conn, connector_response_update).await } } + +#[async_trait::async_trait] +impl ConnectorResponseInterface for MockDb { + async fn insert_connector_response( + &self, + new: ConnectorResponseNew, + ) -> CustomResult { + let mut connector_response = self.connector_response.lock().await; + let response = ConnectorResponse { + id: connector_response.len() as i32, + payment_id: new.payment_id, + merchant_id: new.merchant_id, + txn_id: new.txn_id, + created_at: new.created_at, + modified_at: new.modified_at, + connector_name: new.connector_name, + connector_transaction_id: new.connector_transaction_id, + authentication_data: new.authentication_data, + encoded_data: new.encoded_data, + }; + connector_response.push(response.clone()); + Ok(response) + } + + async fn find_connector_response_by_payment_id_merchant_id_txn_id( + &self, + _payment_id: &str, + _merchant_id: &str, + _txn_id: &str, + ) -> CustomResult { + todo!() + } + + async fn update_connector_response( + &self, + this: ConnectorResponse, + connector_response_update: ConnectorResponseUpdate, + ) -> CustomResult { + let mut connector_response = self.connector_response.lock().await; + let response = connector_response + .iter_mut() + .find(|item| item.id == this.id) + .unwrap(); + *response = connector_response_update.apply_changeset(response.clone()); + Ok(response.clone()) + } +} diff --git a/crates/router/src/db/customers.rs b/crates/router/src/db/customers.rs index b405bc7c15..747376f9db 100644 --- a/crates/router/src/db/customers.rs +++ b/crates/router/src/db/customers.rs @@ -1,7 +1,7 @@ +use super::MockDb; use crate::{ connection::pg_connection, core::errors::{self, CustomResult}, - services::Store, types::{ api::CreateCustomerRequest, storage::{Customer, CustomerNew, CustomerUpdate}, @@ -9,7 +9,7 @@ use crate::{ }; #[async_trait::async_trait] -pub trait ICustomer { +pub trait CustomerInterface { async fn delete_customer_by_customer_id_merchant_id( &self, customer_id: &str, @@ -42,7 +42,7 @@ pub trait ICustomer { } #[async_trait::async_trait] -impl ICustomer for Store { +impl CustomerInterface for super::Store { async fn find_customer_optional_by_customer_id_merchant_id( &self, customer_id: &str, @@ -76,7 +76,7 @@ impl ICustomer for Store { customer_data: CustomerNew, ) -> CustomResult { let conn = pg_connection(&self.master_pool.conn).await; - customer_data.insert(&conn).await + customer_data.insert_diesel(&conn).await } async fn delete_customer_by_customer_id_merchant_id( @@ -88,3 +88,70 @@ impl ICustomer for Store { Customer::delete_by_customer_id_merchant_id(&conn, customer_id, merchant_id).await } } + +#[async_trait::async_trait] +impl CustomerInterface for MockDb { + #[allow(clippy::panic)] + async fn find_customer_optional_by_customer_id_merchant_id( + &self, + customer_id: &str, + merchant_id: &str, + ) -> CustomResult, errors::StorageError> { + let customers = self.customers.lock().await; + + Ok(customers + .iter() + .find(|customer| { + customer.customer_id == customer_id && customer.merchant_id == merchant_id + }) + .cloned()) + } + + async fn update_customer_by_customer_id_merchant_id( + &self, + _customer_id: String, + _merchant_id: String, + _customer: CustomerUpdate, + ) -> CustomResult { + todo!() + } + + async fn find_customer_by_customer_id_merchant_id( + &self, + _customer_id: &str, + _merchant_id: &str, + ) -> CustomResult { + todo!() + } + + #[allow(clippy::panic)] + async fn insert_customer( + &self, + customer_data: CustomerNew, + ) -> CustomResult { + let mut customers = self.customers.lock().await; + let customer = Customer { + id: customers.len() as i32, + customer_id: customer_data.customer_id, + merchant_id: customer_data.merchant_id, + name: customer_data.name, + email: customer_data.email, + phone: customer_data.phone, + phone_country_code: customer_data.phone_country_code, + description: customer_data.description, + address: customer_data.address, + created_at: common_utils::date_time::now(), + metadata: customer_data.metadata, + }; + customers.push(customer.clone()); + Ok(customer) + } + + async fn delete_customer_by_customer_id_merchant_id( + &self, + _customer_id: &str, + _merchant_id: &str, + ) -> CustomResult { + todo!() + } +} diff --git a/crates/router/src/db/events.rs b/crates/router/src/db/events.rs index ff104a7bf9..2bbf75204a 100644 --- a/crates/router/src/db/events.rs +++ b/crates/router/src/db/events.rs @@ -1,19 +1,26 @@ +use super::MockDb; use crate::{ connection::pg_connection, core::errors::{self, CustomResult}, - services::Store, types::storage::{Event, EventNew}, }; #[async_trait::async_trait] -pub trait IEvent { +pub trait EventInterface { async fn insert_event(&self, event: EventNew) -> CustomResult; } #[async_trait::async_trait] -impl IEvent for Store { +impl EventInterface for super::Store { async fn insert_event(&self, event: EventNew) -> CustomResult { let conn = pg_connection(&self.master_pool.conn).await; event.insert(&conn).await } } + +#[async_trait::async_trait] +impl EventInterface for MockDb { + async fn insert_event(&self, _event: EventNew) -> CustomResult { + todo!() + } +} diff --git a/crates/router/src/db/locker_mock_up.rs b/crates/router/src/db/locker_mock_up.rs index 1bbef80ebc..11bea2f211 100644 --- a/crates/router/src/db/locker_mock_up.rs +++ b/crates/router/src/db/locker_mock_up.rs @@ -1,12 +1,12 @@ +use super::MockDb; use crate::{ connection::pg_connection, core::errors::{self, CustomResult}, - services::Store, types::storage::{LockerMockUp, LockerMockUpNew}, }; #[async_trait::async_trait] -pub trait ILockerMockUp { +pub trait LockerMockUpInterface { async fn find_locker_by_card_id( &self, card_id: &str, @@ -19,7 +19,7 @@ pub trait ILockerMockUp { } #[async_trait::async_trait] -impl ILockerMockUp for Store { +impl LockerMockUpInterface for super::Store { async fn find_locker_by_card_id( &self, card_id: &str, @@ -36,3 +36,20 @@ impl ILockerMockUp for Store { new.insert(&conn).await } } + +#[async_trait::async_trait] +impl LockerMockUpInterface for MockDb { + async fn find_locker_by_card_id( + &self, + _card_id: &str, + ) -> CustomResult { + todo!() + } + + async fn insert_locker_mock_up( + &self, + _new: LockerMockUpNew, + ) -> CustomResult { + todo!() + } +} diff --git a/crates/router/src/db/mandate.rs b/crates/router/src/db/mandate.rs index 3810bbf2cf..eaeb43b0bd 100644 --- a/crates/router/src/db/mandate.rs +++ b/crates/router/src/db/mandate.rs @@ -1,12 +1,12 @@ +use super::MockDb; use crate::{ connection::pg_connection, core::errors::{self, CustomResult}, - services::Store, types::storage::{Mandate, MandateNew, MandateUpdate}, }; #[async_trait::async_trait] -pub trait IMandate { +pub trait MandateInterface { async fn find_mandate_by_merchant_id_mandate_id( &self, merchant_id: &str, @@ -33,7 +33,7 @@ pub trait IMandate { } #[async_trait::async_trait] -impl IMandate for Store { +impl MandateInterface for super::Store { async fn find_mandate_by_merchant_id_mandate_id( &self, merchant_id: &str, @@ -70,3 +70,38 @@ impl IMandate for Store { mandate.insert(&conn).await } } + +#[async_trait::async_trait] +impl MandateInterface for MockDb { + async fn find_mandate_by_merchant_id_mandate_id( + &self, + _merchant_id: &str, + _mandate_id: &str, + ) -> CustomResult { + todo!() + } + + async fn find_mandate_by_merchant_id_customer_id( + &self, + _merchant_id: &str, + _customer_id: &str, + ) -> CustomResult, errors::StorageError> { + todo!() + } + + async fn update_mandate_by_merchant_id_mandate_id( + &self, + _merchant_id: &str, + _mandate_id: &str, + _mandate: MandateUpdate, + ) -> CustomResult { + todo!() + } + + async fn insert_mandate( + &self, + _mandate: MandateNew, + ) -> CustomResult { + todo!() + } +} diff --git a/crates/router/src/db/merchant_account.rs b/crates/router/src/db/merchant_account.rs index 22ceb94818..40bd00625e 100644 --- a/crates/router/src/db/merchant_account.rs +++ b/crates/router/src/db/merchant_account.rs @@ -1,12 +1,15 @@ +use error_stack::Report; +use masking::PeekInterface; + +use super::MockDb; use crate::{ connection::pg_connection, - core::errors::{self, CustomResult}, - services::Store, + core::errors::{self, CustomResult, DatabaseError, StorageError}, types::storage::{MerchantAccount, MerchantAccountNew, MerchantAccountUpdate}, }; #[async_trait::async_trait] -pub trait IMerchantAccount { +pub trait MerchantAccountInterface { async fn insert_merchant( &self, merchant_account: MerchantAccountNew, @@ -40,13 +43,13 @@ pub trait IMerchantAccount { } #[async_trait::async_trait] -impl IMerchantAccount for Store { +impl MerchantAccountInterface for super::Store { async fn insert_merchant( &self, merchant_account: MerchantAccountNew, ) -> CustomResult { let conn = pg_connection(&self.master_pool.conn).await; - merchant_account.insert(&conn).await + merchant_account.insert_diesel(&conn).await } async fn find_merchant_account_by_merchant_id( @@ -90,3 +93,89 @@ impl IMerchantAccount for Store { MerchantAccount::delete_by_merchant_id(&conn, merchant_id).await } } + +#[async_trait::async_trait] +impl MerchantAccountInterface for MockDb { + #[allow(clippy::panic)] + async fn insert_merchant( + &self, + merchant_account: MerchantAccountNew, + ) -> CustomResult { + let mut accounts = self.merchant_accounts.lock().await; + let account = MerchantAccount { + id: accounts.len() as i32, + merchant_id: merchant_account.merchant_id, + api_key: merchant_account.api_key, + return_url: merchant_account.return_url, + enable_payment_response_hash: merchant_account + .enable_payment_response_hash + .unwrap_or_default(), + payment_response_hash_key: merchant_account.payment_response_hash_key, + redirect_to_merchant_with_http_post: merchant_account + .redirect_to_merchant_with_http_post + .unwrap_or_default(), + merchant_name: merchant_account.merchant_name, + merchant_details: merchant_account.merchant_details, + webhook_details: merchant_account.webhook_details, + routing_algorithm: merchant_account.routing_algorithm, + custom_routing_rules: merchant_account.custom_routing_rules, + sub_merchants_enabled: merchant_account.sub_merchants_enabled, + parent_merchant_id: merchant_account.parent_merchant_id, + publishable_key: merchant_account.publishable_key, + }; + accounts.push(account.clone()); + Ok(account) + } + + #[allow(clippy::panic)] + async fn find_merchant_account_by_merchant_id( + &self, + merchant_id: &str, + ) -> CustomResult { + let accounts = self.merchant_accounts.lock().await; + let account = accounts + .iter() + .find(|account| account.merchant_id == merchant_id); + + match account { + Some(account) => Ok(account.clone()), + None => todo!(), + } + } + + async fn update_merchant( + &self, + _this: MerchantAccount, + _merchant_account: MerchantAccountUpdate, + ) -> CustomResult { + todo!() + } + + #[allow(clippy::panic)] + async fn find_merchant_account_by_api_key( + &self, + api_key: &str, + ) -> CustomResult { + let accounts = self.merchant_accounts.lock().await; + + accounts + .iter() + .find(|account| account.api_key.as_ref().map(|s| s.peek()) == Some(&api_key.into())) + .cloned() + .ok_or_else(|| Report::from(StorageError::DatabaseError(DatabaseError::NotFound))) + } + + async fn find_merchant_account_by_publishable_key( + &self, + _publishable_key: &str, + ) -> CustomResult { + todo!() + } + + async fn delete_merchant_account_by_merchant_id( + &self, + _merchant_id: &str, + ) -> CustomResult { + todo!() + } +} diff --git a/crates/router/src/db/merchant_connector_account.rs b/crates/router/src/db/merchant_connector_account.rs index d38b495d97..2bbf5b4f87 100644 --- a/crates/router/src/db/merchant_connector_account.rs +++ b/crates/router/src/db/merchant_connector_account.rs @@ -1,14 +1,16 @@ +use masking::ExposeInterface; + +use super::MockDb; use crate::{ connection::pg_connection, core::errors::{self, CustomResult}, - services::Store, types::storage::{ MerchantConnectorAccount, MerchantConnectorAccountNew, MerchantConnectorAccountUpdate, }, }; #[async_trait::async_trait] -pub trait IMerchantConnectorAccount { +pub trait MerchantConnectorAccountInterface { async fn find_merchant_connector_account_by_merchant_id_connector( &self, merchant_id: &str, @@ -45,7 +47,7 @@ pub trait IMerchantConnectorAccount { } #[async_trait::async_trait] -impl IMerchantConnectorAccount for Store { +impl MerchantConnectorAccountInterface for super::Store { async fn find_merchant_connector_account_by_merchant_id_connector( &self, merchant_id: &str, @@ -74,7 +76,7 @@ impl IMerchantConnectorAccount for Store { t: MerchantConnectorAccountNew, ) -> CustomResult { let conn = pg_connection(&self.master_pool.conn).await; - t.insert(&conn).await + t.insert_diesel(&conn).await } async fn find_merchant_connector_account_by_merchant_id_list( @@ -108,3 +110,76 @@ impl IMerchantConnectorAccount for Store { .await } } + +#[async_trait::async_trait] +impl MerchantConnectorAccountInterface for MockDb { + async fn find_merchant_connector_account_by_merchant_id_connector( + &self, + merchant_id: &str, + connector: &str, + ) -> CustomResult { + let accounts = self.merchant_connector_accounts.lock().await; + let account = accounts + .iter() + .find(|account| { + account.merchant_id == merchant_id && account.connector_name == connector + }) + .cloned() + .unwrap(); + Ok(account) + } + + async fn find_by_merchant_connector_account_merchant_id_merchant_connector_id( + &self, + _merchant_id: &str, + _merchant_connector_id: &i32, + ) -> CustomResult { + todo!() + } + + #[allow(clippy::panic)] + async fn insert_merchant_connector_account( + &self, + t: MerchantConnectorAccountNew, + ) -> CustomResult { + let mut accounts = self.merchant_connector_accounts.lock().await; + let account = MerchantConnectorAccount { + id: accounts.len() as i32, + merchant_id: t.merchant_id.unwrap_or_default(), + connector_name: t.connector_name.unwrap_or_default(), + connector_account_details: t.connector_account_details.unwrap_or_default().expose(), + test_mode: t.test_mode, + disabled: t.disabled, + merchant_connector_id: t.merchant_connector_id.unwrap_or_default(), + payment_methods_enabled: t.payment_methods_enabled, + connector_type: t + .connector_type + .unwrap_or(crate::types::storage::enums::ConnectorType::FinOperations), + }; + accounts.push(account.clone()); + Ok(account) + } + + async fn find_merchant_connector_account_by_merchant_id_list( + &self, + _merchant_id: &str, + ) -> CustomResult, errors::StorageError> { + todo!() + } + + async fn update_merchant_connector_account( + &self, + _this: MerchantConnectorAccount, + _merchant_connector_account: MerchantConnectorAccountUpdate, + ) -> CustomResult { + todo!() + } + + async fn delete_merchant_connector_account_by_merchant_id_merchant_connector_id( + &self, + _merchant_id: &str, + _merchant_connector_id: &i32, + ) -> CustomResult { + todo!() + } +} diff --git a/crates/router/src/db/payment_attempt.rs b/crates/router/src/db/payment_attempt.rs index 1451d874a6..5cf6ce492f 100644 --- a/crates/router/src/db/payment_attempt.rs +++ b/crates/router/src/db/payment_attempt.rs @@ -1,10 +1,11 @@ +use super::MockDb; use crate::{ core::errors::{self, CustomResult}, types::storage::{PaymentAttempt, PaymentAttemptNew, PaymentAttemptUpdate}, }; #[async_trait::async_trait] -pub trait IPaymentAttempt { +pub trait PaymentAttemptInterface { async fn insert_payment_attempt( &self, payment_attempt: PaymentAttemptNew, @@ -50,7 +51,7 @@ pub trait IPaymentAttempt { #[cfg(not(feature = "kv_store"))] mod storage { - use super::IPaymentAttempt; + use super::PaymentAttemptInterface; use crate::{ connection::pg_connection, core::errors::{self, CustomResult}, @@ -59,13 +60,13 @@ mod storage { }; #[async_trait::async_trait] - impl IPaymentAttempt for Store { + impl PaymentAttemptInterface for Store { async fn insert_payment_attempt( &self, payment_attempt: PaymentAttemptNew, ) -> CustomResult { let conn = pg_connection(&self.master_pool.conn).await; - payment_attempt.insert(&conn).await + payment_attempt.insert_diesel(&conn).await } async fn update_payment_attempt( @@ -144,6 +145,120 @@ mod storage { } } +#[async_trait::async_trait] +impl PaymentAttemptInterface for MockDb { + async fn find_payment_attempt_by_merchant_id_txn_id( + &self, + _merchant_id: &str, + _txn_id: &str, + ) -> CustomResult { + todo!() + } + + async fn find_payment_attempt_by_merchant_id_connector_txn_id( + &self, + _merchant_id: &str, + _connector_txn_id: &str, + ) -> CustomResult { + todo!() + } + + #[allow(clippy::panic)] + async fn insert_payment_attempt( + &self, + payment_attempt: PaymentAttemptNew, + ) -> CustomResult { + let mut payment_attempts = self.payment_attempts.lock().await; + let id = payment_attempts.len() as i32; + let time = common_utils::date_time::now(); + + let payment_attempt = PaymentAttempt { + id, + payment_id: payment_attempt.payment_id, + merchant_id: payment_attempt.merchant_id, + txn_id: payment_attempt.txn_id, + status: payment_attempt.status, + amount: payment_attempt.amount, + currency: payment_attempt.currency, + save_to_locker: payment_attempt.save_to_locker, + connector: payment_attempt.connector, + error_message: payment_attempt.error_message, + offer_amount: payment_attempt.offer_amount, + surcharge_amount: payment_attempt.surcharge_amount, + tax_amount: payment_attempt.tax_amount, + payment_method_id: payment_attempt.payment_method_id, + payment_method: payment_attempt.payment_method, + payment_flow: payment_attempt.payment_flow, + redirect: payment_attempt.redirect, + connector_transaction_id: payment_attempt.connector_transaction_id, + capture_method: payment_attempt.capture_method, + capture_on: payment_attempt.capture_on, + confirm: payment_attempt.confirm, + authentication_type: payment_attempt.authentication_type, + created_at: payment_attempt.created_at.unwrap_or(time), + modified_at: payment_attempt.modified_at.unwrap_or(time), + last_synced: payment_attempt.last_synced, + cancellation_reason: payment_attempt.cancellation_reason, + amount_to_capture: payment_attempt.amount_to_capture, + mandate_id: None, + browser_info: None, + }; + payment_attempts.push(payment_attempt.clone()); + Ok(payment_attempt) + } + + async fn update_payment_attempt( + &self, + this: PaymentAttempt, + payment_attempt: PaymentAttemptUpdate, + ) -> CustomResult { + let mut payment_attempts = self.payment_attempts.lock().await; + + let item = payment_attempts + .iter_mut() + .find(|item| item.id == this.id) + .unwrap(); + + *item = payment_attempt.apply_changeset(this); + + Ok(item.clone()) + } + + async fn find_payment_attempt_by_payment_id_merchant_id( + &self, + _payment_id: &str, + _merchant_id: &str, + ) -> CustomResult { + todo!() + } + + async fn find_payment_attempt_by_transaction_id_payment_id_merchant_id( + &self, + _transaction_id: &str, + _payment_id: &str, + _merchant_id: &str, + ) -> CustomResult { + todo!() + } + + async fn find_payment_attempt_last_successful_attempt_by_payment_id_merchant_id( + &self, + payment_id: &str, + merchant_id: &str, + ) -> CustomResult { + let payment_attempts = self.payment_attempts.lock().await; + + Ok(payment_attempts + .iter() + .find(|payment_attempt| { + payment_attempt.payment_id == payment_id + && payment_attempt.merchant_id == merchant_id + }) + .cloned() + .unwrap()) + } +} + #[cfg(feature = "kv_store")] mod storage { use common_utils::date_time; @@ -151,7 +266,7 @@ mod storage { use fred::prelude::*; use redis_interface::RedisEntryId; - use super::IPaymentAttempt; + use super::PaymentAttemptInterface; use crate::{ connection::pg_connection, core::errors::{self, CustomResult}, @@ -161,7 +276,7 @@ mod storage { }; #[async_trait::async_trait] - impl IPaymentAttempt for Store { + impl PaymentAttemptInterface for Store { async fn insert_payment_attempt( &self, payment_attempt: PaymentAttemptNew, @@ -221,7 +336,7 @@ mod storage { Ok(1) => { let conn = pg_connection(&self.master_pool.conn).await; let query = payment_attempt - .insert(&conn) + .insert_diesel(&conn) .await .change_context(errors::StorageError::KVError)?; let stream_name = self.drainer_stream(&PaymentAttempt::shard_key( @@ -356,16 +471,16 @@ mod storage { async fn find_payment_attempt_by_merchant_id_connector_txn_id( &self, - merchant_id: &str, - connector_txn_id: &str, + _merchant_id: &str, + _connector_txn_id: &str, ) -> CustomResult { Err(errors::StorageError::KVError).into_report() } async fn find_payment_attempt_by_merchant_id_txn_id( &self, - merchant_id: &str, - txn_id: &str, + _merchant_id: &str, + _txn_id: &str, ) -> CustomResult { Err(errors::StorageError::KVError).into_report() } diff --git a/crates/router/src/db/payment_intent.rs b/crates/router/src/db/payment_intent.rs index 1dfa9fdb68..7d28026931 100644 --- a/crates/router/src/db/payment_intent.rs +++ b/crates/router/src/db/payment_intent.rs @@ -1,3 +1,4 @@ +use super::MockDb; use crate::{ core::errors::{self, CustomResult}, types::{ @@ -7,7 +8,7 @@ use crate::{ }; #[async_trait::async_trait] -pub trait IPaymentIntent { +pub trait PaymentIntentInterface { async fn update_payment_intent( &self, this: PaymentIntent, @@ -39,7 +40,7 @@ mod storage { use fred::prelude::{RedisErrorKind, *}; use redis_interface::RedisEntryId; - use super::IPaymentIntent; + use super::PaymentIntentInterface; use crate::{ connection::pg_connection, core::errors::{self, CustomResult}, @@ -49,7 +50,7 @@ mod storage { }; #[async_trait::async_trait] - impl IPaymentIntent for Store { + impl PaymentIntentInterface for Store { async fn insert_payment_intent( &self, new: PaymentIntentNew, @@ -96,7 +97,7 @@ mod storage { Ok(1) => { let conn = pg_connection(&self.master_pool.conn).await; let query = new - .insert(&conn) + .insert_diesel(&conn) .await .change_context(errors::StorageError::KVError)?; let stream_name = self.drainer_stream(&PaymentIntent::shard_key( @@ -197,8 +198,8 @@ mod storage { } async fn filter_payment_intent_by_constraints( &self, - merchant_id: &str, - pc: &api::PaymentListConstraints, + _merchant_id: &str, + _pc: &api::PaymentListConstraints, ) -> CustomResult, errors::StorageError> { //TODO: Implement this Err(errors::StorageError::KVError.into()) @@ -208,7 +209,7 @@ mod storage { #[cfg(not(feature = "kv_store"))] mod storage { - use super::IPaymentIntent; + use super::PaymentIntentInterface; use crate::{ connection::pg_connection, core::errors::{self, CustomResult}, @@ -217,13 +218,13 @@ mod storage { }; #[async_trait::async_trait] - impl IPaymentIntent for Store { + impl PaymentIntentInterface for Store { async fn insert_payment_intent( &self, new: PaymentIntentNew, ) -> CustomResult { let conn = pg_connection(&self.master_pool.conn).await; - new.insert(&conn).await + new.insert_diesel(&conn).await } async fn update_payment_intent( @@ -254,3 +255,79 @@ mod storage { } } } + +#[async_trait::async_trait] +impl PaymentIntentInterface for MockDb { + async fn filter_payment_intent_by_constraints( + &self, + _merchant_id: &str, + _pc: &api::PaymentListConstraints, + ) -> CustomResult, errors::StorageError> { + todo!() + } + + #[allow(clippy::panic)] + async fn insert_payment_intent( + &self, + new: PaymentIntentNew, + ) -> CustomResult { + let mut payment_intents = self.payment_intents.lock().await; + let time = common_utils::date_time::now(); + let payment_intent = PaymentIntent { + id: payment_intents.len() as i32, + payment_id: new.payment_id, + merchant_id: new.merchant_id, + status: new.status, + amount: new.amount, + currency: new.currency, + amount_captured: new.amount_captured, + customer_id: new.customer_id, + description: new.description, + return_url: new.return_url, + metadata: new.metadata, + connector_id: new.connector_id, + shipping_address_id: new.shipping_address_id, + billing_address_id: new.billing_address_id, + statement_descriptor_name: new.statement_descriptor_name, + statement_descriptor_suffix: new.statement_descriptor_suffix, + created_at: new.created_at.unwrap_or(time), + modified_at: new.modified_at.unwrap_or(time), + last_synced: new.last_synced, + setup_future_usage: new.setup_future_usage, + off_session: new.off_session, + client_secret: new.client_secret, + }; + payment_intents.push(payment_intent.clone()); + Ok(payment_intent) + } + + async fn update_payment_intent( + &self, + this: PaymentIntent, + update: PaymentIntentUpdate, + ) -> CustomResult { + let mut payment_intents = self.payment_intents.lock().await; + let payment_intent = payment_intents + .iter_mut() + .find(|item| item.id == this.id) + .unwrap(); + *payment_intent = update.apply_changeset(this); + Ok(payment_intent.clone()) + } + + async fn find_payment_intent_by_payment_id_merchant_id( + &self, + payment_id: &str, + merchant_id: &str, + ) -> CustomResult { + let payment_intents = self.payment_intents.lock().await; + + Ok(payment_intents + .iter() + .find(|payment_intent| { + payment_intent.payment_id == payment_id && payment_intent.merchant_id == merchant_id + }) + .cloned() + .unwrap()) + } +} diff --git a/crates/router/src/db/payment_method.rs b/crates/router/src/db/payment_method.rs index 51aeb32932..a7287c5b70 100644 --- a/crates/router/src/db/payment_method.rs +++ b/crates/router/src/db/payment_method.rs @@ -1,12 +1,12 @@ +use super::MockDb; use crate::{ connection::pg_connection, core::errors::{self, CustomResult}, - services::Store, types::storage::{PaymentMethod, PaymentMethodNew}, }; #[async_trait::async_trait] -pub trait IPaymentMethod { +pub trait PaymentMethodInterface { async fn find_payment_method( &self, payment_method_id: &str, @@ -31,7 +31,7 @@ pub trait IPaymentMethod { } #[async_trait::async_trait] -impl IPaymentMethod for Store { +impl PaymentMethodInterface for super::Store { async fn find_payment_method( &self, payment_method_id: &str, @@ -71,3 +71,36 @@ impl IPaymentMethod for Store { .await } } + +#[async_trait::async_trait] +impl PaymentMethodInterface for MockDb { + async fn find_payment_method( + &self, + _payment_method_id: &str, + ) -> CustomResult { + todo!() + } + + async fn insert_payment_method( + &self, + _m: PaymentMethodNew, + ) -> CustomResult { + todo!() + } + + async fn find_payment_method_by_customer_id_merchant_id_list( + &self, + _customer_id: &str, + _merchant_id: &str, + ) -> CustomResult, errors::StorageError> { + todo!() + } + + async fn delete_payment_method_by_merchant_id_payment_method_id( + &self, + _merchant_id: &str, + _payment_method_id: &str, + ) -> CustomResult { + todo!() + } +} diff --git a/crates/router/src/db/process_tracker.rs b/crates/router/src/db/process_tracker.rs index 6f1ccbf3b4..ffc639c76d 100644 --- a/crates/router/src/db/process_tracker.rs +++ b/crates/router/src/db/process_tracker.rs @@ -1,14 +1,14 @@ use time::PrimitiveDateTime; +use super::MockDb; use crate::{ connection::pg_connection, core::errors::{self, CustomResult}, - services::Store, types::storage::{enums, ProcessTracker, ProcessTrackerNew, ProcessTrackerUpdate}, }; #[async_trait::async_trait] -pub trait IProcessTracker { +pub trait ProcessTrackerInterface { async fn reinitialize_limbo_processes( &self, ids: Vec, @@ -52,7 +52,7 @@ pub trait IProcessTracker { } #[async_trait::async_trait] -impl IProcessTracker for Store { +impl ProcessTrackerInterface for super::Store { async fn find_process_by_id( &self, id: &str, @@ -123,3 +123,87 @@ impl IProcessTracker for Store { ProcessTracker::update_process_status_by_ids(&conn, task_ids, task_update).await } } + +#[async_trait::async_trait] +impl ProcessTrackerInterface for MockDb { + async fn find_process_by_id( + &self, + id: &str, + ) -> CustomResult, errors::StorageError> { + let optional = self + .processes + .lock() + .await + .iter() + .find(|process| process.id == id) + .cloned(); + + Ok(optional) + } + + async fn reinitialize_limbo_processes( + &self, + _ids: Vec, + _schedule_time: PrimitiveDateTime, + ) -> CustomResult { + todo!() + } + + async fn find_processes_by_time_status( + &self, + _time_lower_limit: PrimitiveDateTime, + _time_upper_limit: PrimitiveDateTime, + _status: enums::ProcessTrackerStatus, + _limit: Option, + ) -> CustomResult, errors::StorageError> { + todo!() + } + + async fn insert_process( + &self, + new: ProcessTrackerNew, + ) -> CustomResult { + let mut processes = self.processes.lock().await; + let process = ProcessTracker { + id: new.id, + name: new.name, + tag: new.tag, + runner: new.runner, + retry_count: new.retry_count, + schedule_time: new.schedule_time, + rule: new.rule, + tracking_data: new.tracking_data, + business_status: new.business_status, + status: new.status, + event: new.event, + created_at: new.created_at, + updated_at: new.updated_at, + }; + processes.push(process.clone()); + Ok(process) + } + + async fn update_process( + &self, + _this: ProcessTracker, + _process: ProcessTrackerUpdate, + ) -> CustomResult { + todo!() + } + + async fn update_process_tracker( + &self, + _this: ProcessTracker, + _process: ProcessTrackerUpdate, + ) -> CustomResult { + todo!() + } + + async fn process_tracker_update_process_status_by_ids( + &self, + _task_ids: Vec, + _task_update: ProcessTrackerUpdate, + ) -> CustomResult, errors::StorageError> { + todo!() + } +} diff --git a/crates/router/src/db/queue.rs b/crates/router/src/db/queue.rs new file mode 100644 index 0000000000..115a818f55 --- /dev/null +++ b/crates/router/src/db/queue.rs @@ -0,0 +1,167 @@ +use redis_interface::{errors::RedisError, RedisEntryId, SetNXReply}; +use router_env::logger; + +use super::MockDb; +use crate::{ + core::errors::{CustomResult, ProcessTrackerError}, + types::storage::ProcessTracker, +}; + +#[async_trait::async_trait] +pub trait QueueInterface { + async fn fetch_consumer_tasks( + &self, + stream_name: &str, + group_name: &str, + consumer_name: &str, + ) -> CustomResult, ProcessTrackerError>; + + async fn consumer_group_create( + &self, + stream: &str, + group: &str, + id: &RedisEntryId, + ) -> CustomResult<(), RedisError>; + + async fn acquire_pt_lock(&self, tag: &str, lock_key: &str, lock_val: &str, ttl: i64) -> bool; + + async fn release_pt_lock(&self, tag: &str, lock_key: &str) -> bool; + + async fn stream_append_entry( + &self, + stream: &str, + entry_id: &RedisEntryId, + fields: Vec<(&str, String)>, + ) -> CustomResult<(), RedisError>; + + async fn get_key(&self, key: &str) -> CustomResult, RedisError>; +} + +#[async_trait::async_trait] +impl QueueInterface for super::Store { + async fn fetch_consumer_tasks( + &self, + stream_name: &str, + group_name: &str, + consumer_name: &str, + ) -> CustomResult, ProcessTrackerError> { + crate::scheduler::consumer::fetch_consumer_tasks( + self, + &self.redis_conn.clone(), + stream_name, + group_name, + consumer_name, + ) + .await + } + + async fn consumer_group_create( + &self, + stream: &str, + group: &str, + id: &RedisEntryId, + ) -> CustomResult<(), RedisError> { + self.redis_conn + .consumer_group_create(stream, group, id) + .await + } + + async fn acquire_pt_lock(&self, tag: &str, lock_key: &str, lock_val: &str, ttl: i64) -> bool { + let conn = self.redis_conn.clone(); + let is_lock_acquired = conn.set_key_if_not_exist(lock_key, lock_val).await; + match is_lock_acquired { + Ok(SetNXReply::KeySet) => match conn.set_expiry(lock_key, ttl).await { + Ok(()) => true, + + #[allow(unused_must_use)] + Err(error) => { + logger::error!(error=?error.current_context()); + conn.delete_key(lock_key).await; + false + } + }, + Ok(SetNXReply::KeyNotSet) => { + logger::error!(%tag, "Lock not acquired, previous fetch still in progress"); + false + } + Err(error) => { + logger::error!(error=%error.current_context(), %tag, "Error while locking"); + false + } + } + } + + async fn release_pt_lock(&self, tag: &str, lock_key: &str) -> bool { + let is_lock_released = self.redis_conn.delete_key(lock_key).await; + match is_lock_released { + Ok(()) => true, + Err(error) => { + logger::error!(error=%error.current_context(), %tag, "Error while releasing lock"); + false + } + } + } + + async fn stream_append_entry( + &self, + stream: &str, + entry_id: &RedisEntryId, + fields: Vec<(&str, String)>, + ) -> CustomResult<(), RedisError> { + self.redis_conn + .stream_append_entry(stream, entry_id, fields) + .await + } + + async fn get_key(&self, key: &str) -> CustomResult, RedisError> { + self.redis_conn.get_key::>(key).await + } +} + +#[async_trait::async_trait] +impl QueueInterface for MockDb { + async fn fetch_consumer_tasks( + &self, + _stream_name: &str, + _group_name: &str, + _consumer_name: &str, + ) -> CustomResult, ProcessTrackerError> { + todo!() + } + + async fn consumer_group_create( + &self, + _stream: &str, + _group: &str, + _id: &RedisEntryId, + ) -> CustomResult<(), RedisError> { + todo!() + } + + async fn acquire_pt_lock( + &self, + _tag: &str, + _lock_key: &str, + _lock_val: &str, + _ttl: i64, + ) -> bool { + todo!() + } + + async fn release_pt_lock(&self, _tag: &str, _lock_key: &str) -> bool { + todo!() + } + + async fn stream_append_entry( + &self, + _stream: &str, + _entry_id: &RedisEntryId, + _fields: Vec<(&str, String)>, + ) -> CustomResult<(), RedisError> { + todo!() + } + + async fn get_key(&self, key: &str) -> CustomResult, RedisError> { + self.redis.get_key(key).await + } +} diff --git a/crates/router/src/db/refund.rs b/crates/router/src/db/refund.rs index cf8cbc35f6..821a589a62 100644 --- a/crates/router/src/db/refund.rs +++ b/crates/router/src/db/refund.rs @@ -1,12 +1,14 @@ +use error_stack::Report; + +use super::MockDb; use crate::{ connection::pg_connection, - core::errors::{self, CustomResult}, - services::Store, + core::errors::{self, CustomResult, DatabaseError, StorageError}, types::storage::{Refund, RefundNew, RefundUpdate}, }; #[async_trait::async_trait] -pub trait IRefund { +pub trait RefundInterface { async fn find_refund_by_internal_reference_id_merchant_id( &self, internal_reference_id: &str, @@ -48,7 +50,7 @@ pub trait IRefund { } #[async_trait::async_trait] -impl IRefund for Store { +impl RefundInterface for super::Store { async fn find_refund_by_internal_reference_id_merchant_id( &self, internal_reference_id: &str, @@ -110,3 +112,90 @@ impl IRefund for Store { Refund::find_by_payment_id_merchant_id(&conn, payment_id, merchant_id).await } } + +#[async_trait::async_trait] +impl RefundInterface for MockDb { + async fn find_refund_by_internal_reference_id_merchant_id( + &self, + _internal_reference_id: &str, + _merchant_id: &str, + ) -> CustomResult { + todo!() + } + + async fn insert_refund(&self, new: RefundNew) -> CustomResult { + let mut refunds = self.refunds.lock().await; + let current_time = common_utils::date_time::now(); + + let refund = Refund { + id: refunds.len() as i32, + internal_reference_id: new.internal_reference_id, + refund_id: new.refund_id, + payment_id: new.payment_id, + merchant_id: new.merchant_id, + transaction_id: new.transaction_id, + connector: new.connector, + pg_refund_id: new.pg_refund_id, + external_reference_id: new.external_reference_id, + refund_type: new.refund_type, + total_amount: new.total_amount, + currency: new.currency, + refund_amount: new.refund_amount, + refund_status: new.refund_status, + sent_to_gateway: new.sent_to_gateway, + refund_error_message: new.refund_error_message, + metadata: new.metadata, + refund_arn: new.refund_arn, + created_at: new.created_at.unwrap_or(current_time), + updated_at: current_time, + description: new.description, + }; + refunds.push(refund.clone()); + Ok(refund) + } + async fn find_refund_by_merchant_id_transaction_id( + &self, + merchant_id: &str, + txn_id: &str, + ) -> CustomResult, errors::StorageError> { + let refunds = self.refunds.lock().await; + + Ok(refunds + .iter() + .take_while(|refund| { + refund.merchant_id == merchant_id && refund.transaction_id == txn_id + }) + .cloned() + .collect::>()) + } + + async fn update_refund( + &self, + _this: Refund, + _refund: RefundUpdate, + ) -> CustomResult { + todo!() + } + + async fn find_refund_by_merchant_id_refund_id( + &self, + merchant_id: &str, + refund_id: &str, + ) -> CustomResult { + let refunds = self.refunds.lock().await; + + refunds + .iter() + .find(|refund| refund.merchant_id == merchant_id && refund.refund_id == refund_id) + .cloned() + .ok_or_else(|| Report::from(StorageError::DatabaseError(DatabaseError::NotFound))) + } + + async fn find_refund_by_payment_id_merchant_id( + &self, + _payment_id: &str, + _merchant_id: &str, + ) -> CustomResult, errors::StorageError> { + todo!() + } +} diff --git a/crates/router/src/db/temp_card.rs b/crates/router/src/db/temp_card.rs index 9c9dd49765..c9b21870fd 100644 --- a/crates/router/src/db/temp_card.rs +++ b/crates/router/src/db/temp_card.rs @@ -1,12 +1,12 @@ +use super::MockDb; use crate::{ connection::pg_connection, core::errors::{self, CustomResult}, - services::Store, types::storage::{TempCard, TempCardNew}, }; #[async_trait::async_trait] -pub trait ITempCard { +pub trait TempCardInterface { async fn find_tempcard_by_token( &self, token: &i32, @@ -29,13 +29,13 @@ pub trait ITempCard { } #[async_trait::async_trait] -impl ITempCard for Store { +impl TempCardInterface for super::Store { async fn insert_temp_card( &self, address: TempCardNew, ) -> CustomResult { let conn = pg_connection(&self.master_pool.conn).await; - address.insert(&conn).await + address.insert_diesel(&conn).await } async fn find_tempcard_by_transaction_id( @@ -62,3 +62,43 @@ impl ITempCard for Store { TempCard::find_by_token(&conn, token).await } } + +#[async_trait::async_trait] +impl TempCardInterface for MockDb { + #[allow(clippy::panic)] + async fn insert_temp_card( + &self, + insert: TempCardNew, + ) -> CustomResult { + let mut cards = self.temp_cards.lock().await; + let card = TempCard { + id: cards.len() as i32, + date_created: insert.date_created, + txn_id: insert.txn_id, + card_info: insert.card_info, + }; + cards.push(card.clone()); + Ok(card) + } + + async fn find_tempcard_by_transaction_id( + &self, + _transaction_id: &str, + ) -> CustomResult, errors::StorageError> { + todo!() + } + + async fn insert_tempcard_with_token( + &self, + _card: TempCard, + ) -> CustomResult { + todo!() + } + + async fn find_tempcard_by_token( + &self, + _token: &i32, + ) -> CustomResult { + todo!() + } +} diff --git a/crates/router/src/lib.rs b/crates/router/src/lib.rs index c45a76dc7f..928e36878b 100644 --- a/crates/router/src/lib.rs +++ b/crates/router/src/lib.rs @@ -30,13 +30,18 @@ pub mod env; pub mod pii; pub mod routes; pub mod scheduler; + #[allow(unused_imports)] // Allow unused imports only for schema module pub mod schema; pub mod services; pub mod types; pub mod utils; -use actix_web::{dev::Server, middleware::ErrorHandlers}; +use actix_web::{ + body::MessageBody, + dev::{Server, ServiceFactory, ServiceRequest}, + middleware::ErrorHandlers, +}; use http::StatusCode; use routes::AppState; @@ -44,7 +49,6 @@ pub use self::env::logger; use crate::{ configs::settings::Settings, core::errors::{self, BachResult}, - services::Store, }; /// Header Constants @@ -54,6 +58,54 @@ pub mod headers { pub const X_ROUTER: &str = "X-router"; pub const AUTHORIZATION: &str = "Authorization"; } + +pub fn mk_app( + state: AppState, + request_body_limit: usize, +) -> actix_web::App< + impl ServiceFactory< + ServiceRequest, + Config = (), + Response = actix_web::dev::ServiceResponse, + Error = actix_web::Error, + InitError = (), + >, +> { + let json_cfg = actix_web::web::JsonConfig::default() + .limit(request_body_limit) + .content_type_required(true) + .content_type(|mime| mime == mime::APPLICATION_JSON) // FIXME: This doesn't seem to be enforced. + .error_handler(utils::error_parser::custom_json_error_handler); + + let mut server_app = actix_web::App::new() + .app_data(json_cfg) + .wrap(router_env::tracing_actix_web::TracingLogger::default()) + .wrap(ErrorHandlers::new().handler( + StatusCode::NOT_FOUND, + errors::error_handlers::custom_error_handlers, + )) + .wrap(ErrorHandlers::new().handler( + StatusCode::METHOD_NOT_ALLOWED, + errors::error_handlers::custom_error_handlers, + )) + .wrap(cors::cors()) + .service(routes::Payments::server(state.clone())) + .service(routes::Customers::server(state.clone())) + .service(routes::Refunds::server(state.clone())) + .service(routes::Payouts::server(state.clone())) + .service(routes::PaymentMethods::server(state.clone())) + .service(routes::MerchantAccount::server(state.clone())) + .service(routes::MerchantConnectorAccount::server(state.clone())) + .service(routes::Webhooks::server(state.clone())); + + #[cfg(feature = "stripe")] + { + server_app = server_app.service(routes::StripeApis::server(state.clone())); + } + server_app = server_app.service(routes::Health::server(state)); + server_app +} + #[allow(clippy::expect_used, clippy::unwrap_used)] /// # Panics /// @@ -62,53 +114,13 @@ pub async fn start_server(conf: Settings) -> BachResult<(Server, AppState)> { logger::debug!(startup_config=?conf); let server = conf.server.clone(); - let state = routes::AppState { - flow_name: String::from("default"), - store: Store::new(&conf).await, - conf, - }; + let state = routes::AppState::new(conf).await; // Cloning to close connections before shutdown let app_state = state.clone(); - let request_body_limit = server.request_body_limit; - - let server = actix_web::HttpServer::new(move || { - let json_cfg = actix_web::web::JsonConfig::default() - .limit(request_body_limit) - .content_type_required(true) - .content_type(|mime| mime == mime::APPLICATION_JSON) // FIXME: This doesn't seem to be enforced. - .error_handler(utils::error_parser::custom_json_error_handler); - - let mut server_app = actix_web::App::new() - .app_data(json_cfg) - .wrap(router_env::tracing_actix_web::TracingLogger::default()) - .wrap(ErrorHandlers::new().handler( - StatusCode::NOT_FOUND, - errors::error_handlers::custom_error_handlers, - )) - .wrap(ErrorHandlers::new().handler( - StatusCode::METHOD_NOT_ALLOWED, - errors::error_handlers::custom_error_handlers, - )) - .wrap(cors::cors()) - .service(routes::Payments::server(state.clone())) - .service(routes::Customers::server(state.clone())) - .service(routes::Refunds::server(state.clone())) - .service(routes::Payouts::server(state.clone())) - .service(routes::PaymentMethods::server(state.clone())) - .service(routes::MerchantAccount::server(state.clone())) - .service(routes::MerchantConnectorAccount::server(state.clone())) - .service(routes::Webhooks::server(state.clone())); - - #[cfg(feature = "stripe")] - { - server_app = server_app.service(routes::StripeApis::server(state.clone())); - } - server_app = server_app.service(routes::Health::server(state.clone())); - server_app - }) - .bind((server.host.as_str(), server.port))? - .run(); + let server = actix_web::HttpServer::new(move || mk_app(state.clone(), request_body_limit)) + .bind((server.host.as_str(), server.port))? + .run(); Ok((server, app_state)) } diff --git a/crates/router/src/pii.rs b/crates/router/src/pii.rs index ab147b1231..84ae8a8a8f 100644 --- a/crates/router/src/pii.rs +++ b/crates/router/src/pii.rs @@ -22,11 +22,7 @@ where return WithType::fmt(val, f); } - f.write_str(&format!( - "{}{}", - &val_str[..6], - "*".repeat(val_str.len() - 6) - )) + write!(f, "{}{}", &val_str[..6], "*".repeat(val_str.len() - 6)) } } @@ -66,12 +62,11 @@ where return WithType::fmt(val, f); } - let parts: Vec<&str> = val_str.split('@').collect(); - if parts.len() != 2 { - return WithType::fmt(val, f); + if let Some((a, b)) = val_str.split_once('@') { + write!(f, "{}@{}", "*".repeat(a.len()), b) + } else { + WithType::fmt(val, f) } - - f.write_str(&format!("{}@{}", "*".repeat(parts[0].len()), parts[1])) } } @@ -95,7 +90,7 @@ where } } - f.write_str(&format!("{}.**.**.**", segments[0])) + write!(f, "{}.**.**.**", segments[0]) } } diff --git a/crates/router/src/routes/admin.rs b/crates/router/src/routes/admin.rs index 9abcf3c67f..fe62d7d724 100644 --- a/crates/router/src/routes/admin.rs +++ b/crates/router/src/routes/admin.rs @@ -18,7 +18,7 @@ pub async fn merchant_account_create( &state, &req, json_payload.into_inner(), - |state, _, req| create_merchant_account(&state.store, req), + |state, _, req| create_merchant_account(&*state.store, req), api::MerchantAuthentication::AdminApiKey, ) .await @@ -39,7 +39,7 @@ pub async fn retrieve_merchant_account( &state, &req, payload, - |state, _, req| get_merchant_account(&state.store, req), + |state, _, req| get_merchant_account(&*state.store, req), api::MerchantAuthentication::AdminApiKey, ) .await @@ -58,7 +58,7 @@ pub async fn update_merchant_account( &state, &req, json_payload.into_inner(), - |state, _, req| merchant_account_update(&state.store, &merchant_id, req), + |state, _, req| merchant_account_update(&*state.store, &merchant_id, req), api::MerchantAuthentication::AdminApiKey, ) .await @@ -79,7 +79,7 @@ pub async fn delete_merchant_account( &state, &req, payload, - |state, _, req| merchant_account_delete(&state.store, req.merchant_id), + |state, _, req| merchant_account_delete(&*state.store, req.merchant_id), api::MerchantAuthentication::AdminApiKey, ) .await @@ -99,7 +99,7 @@ pub async fn payment_connector_create( &state, &req, json_payload.into_inner(), - |state, _, req| create_payment_connector(&state.store, req, &merchant_id), + |state, _, req| create_payment_connector(&*state.store, req, &merchant_id), api::MerchantAuthentication::AdminApiKey, ) .await @@ -123,7 +123,7 @@ pub async fn payment_connector_retrieve( &req, payload, |state, _, req| { - retrieve_payment_connector(&state.store, req.merchant_id, req.merchant_connector_id) + retrieve_payment_connector(&*state.store, req.merchant_id, req.merchant_connector_id) }, api::MerchantAuthentication::AdminApiKey, ) @@ -144,7 +144,7 @@ pub async fn payment_connector_update( &req, json_payload.into_inner(), |state, _, req| { - update_payment_connector(&state.store, &merchant_id, merchant_connector_id, req) + update_payment_connector(&*state.store, &merchant_id, merchant_connector_id, req) }, api::MerchantAuthentication::AdminApiKey, ) @@ -169,7 +169,7 @@ pub async fn payment_connector_delete( &req, payload, |state, _, req| { - delete_payment_connector(&state.store, req.merchant_id, req.merchant_connector_id) + delete_payment_connector(&*state.store, req.merchant_id, req.merchant_connector_id) }, api::MerchantAuthentication::AdminApiKey, ) diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index 2bddb8f41e..a7923e6eee 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -1,18 +1,67 @@ +use std::sync::Arc; + use actix_web::{web, Scope}; use super::{ admin::*, customers::*, health::*, mandates::*, payment_methods::*, payments::*, payouts::*, refunds::*, webhooks::*, }; -use crate::{configs::settings::Settings, services::Store}; +use crate::{ + configs::settings::Settings, + connection, + db::{MockDb, SqlDb, StorageImpl, StorageInterface}, + services::Store, +}; #[derive(Clone)] pub struct AppState { pub flow_name: String, - pub store: Store, + pub store: Box, pub conf: Settings, } +impl AppState { + pub async fn with_storage(conf: Settings, storage_impl: StorageImpl) -> AppState { + let testable = storage_impl == StorageImpl::DieselPostgresqlTest; + let store: Box = match storage_impl { + StorageImpl::DieselPostgresql | StorageImpl::DieselPostgresqlTest => Box::new(Store { + master_pool: if testable { + SqlDb::test(&conf.master_database).await + } else { + SqlDb::new(&conf.master_database).await + }, + #[cfg(feature = "olap")] + replica_pool: if testable { + SqlDb::test(&conf.replica_database).await + } else { + SqlDb::new(&conf.replica_database).await + }, + // FIXME: from my understanding, this creates a single connection + // for the entire lifetime of the server. This doesn't survive disconnects + // from redis. Consider using connection pool. + redis_conn: Arc::new(connection::redis_connection(&conf).await), + #[cfg(feature = "kv_store")] + config: crate::services::StoreConfig { + drainer_stream_name: conf.drainer.stream_name.clone(), + drainer_num_partitions: conf.drainer.num_partitions, + }, + }), + StorageImpl::Mock => Box::new(MockDb::new(&conf).await), + }; + + AppState { + flow_name: String::from("default"), + store, + conf, + } + } + + #[allow(unused_variables)] + pub async fn new(conf: Settings) -> AppState { + AppState::with_storage(conf, StorageImpl::DieselPostgresql).await + } +} + pub struct Health; impl Health { diff --git a/crates/router/src/routes/customers.rs b/crates/router/src/routes/customers.rs index 538324818e..a0a9365e62 100644 --- a/crates/router/src/routes/customers.rs +++ b/crates/router/src/routes/customers.rs @@ -18,7 +18,7 @@ pub async fn customers_create( &state, &req, json_payload.into_inner(), - |state, merchant_account, req| create_customer(&state.store, merchant_account, req), + |state, merchant_account, req| create_customer(&*state.store, merchant_account, req), api::MerchantAuthentication::ApiKey, ) .await @@ -39,7 +39,7 @@ pub async fn customers_retrieve( &state, &req, payload, - |state, merchant_account, req| retrieve_customer(&state.store, merchant_account, req), + |state, merchant_account, req| retrieve_customer(&*state.store, merchant_account, req), api::MerchantAuthentication::ApiKey, ) .await @@ -59,7 +59,7 @@ pub async fn customers_update( &state, &req, json_payload.into_inner(), - |state, merchant_account, req| update_customer(&state.store, merchant_account, req), + |state, merchant_account, req| update_customer(&*state.store, merchant_account, req), api::MerchantAuthentication::ApiKey, ) .await @@ -80,7 +80,7 @@ pub async fn customers_delete( &state, &req, payload, - |state, merchant_account, req| delete_customer(&state.store, merchant_account, req), + |state, merchant_account, req| delete_customer(&*state.store, merchant_account, req), api::MerchantAuthentication::ApiKey, ) .await diff --git a/crates/router/src/routes/mandates.rs b/crates/router/src/routes/mandates.rs index 399d89fd5a..1f434d1015 100644 --- a/crates/router/src/routes/mandates.rs +++ b/crates/router/src/routes/mandates.rs @@ -41,7 +41,9 @@ pub async fn revoke_mandate( &state, &req, mandate_id, - |state, merchant_account, req| mandate::revoke_mandate(&state.store, merchant_account, req), + |state, merchant_account, req| { + mandate::revoke_mandate(&*state.store, merchant_account, req) + }, api::MerchantAuthentication::ApiKey, ) .await diff --git a/crates/router/src/routes/payment_methods.rs b/crates/router/src/routes/payment_methods.rs index 93f5029f5b..1487b691cd 100644 --- a/crates/router/src/routes/payment_methods.rs +++ b/crates/router/src/routes/payment_methods.rs @@ -49,7 +49,7 @@ pub async fn list_payment_method_api( &req, json_payload.into_inner(), |state, merchant_account, req| { - cards::list_payment_methods(&state.store, merchant_account, req) + cards::list_payment_methods(&*state.store, merchant_account, req) }, api::MerchantAuthentication::ApiKey, ) diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index 57d6fbb7cb..5bafa04d67 100644 --- a/crates/router/src/routes/payments.rs +++ b/crates/router/src/routes/payments.rs @@ -319,7 +319,9 @@ pub async fn payments_list( &state, &req, payload, - |state, merchant_account, req| payments::list_payments(&state.store, merchant_account, req), + |state, merchant_account, req| { + payments::list_payments(&*state.store, merchant_account, req) + }, api::MerchantAuthentication::ApiKey, ) .await diff --git a/crates/router/src/routes/refunds.rs b/crates/router/src/routes/refunds.rs index f1d17c501a..cc19b35242 100644 --- a/crates/router/src/routes/refunds.rs +++ b/crates/router/src/routes/refunds.rs @@ -63,7 +63,7 @@ pub async fn refunds_update( &req, json_payload.into_inner(), |state, merchant_account, req| { - refund_update_core(&state.store, merchant_account, &refund_id, req) + refund_update_core(&*state.store, merchant_account, &refund_id, req) }, api::MerchantAuthentication::ApiKey, ) diff --git a/crates/router/src/scheduler/consumer.rs b/crates/router/src/scheduler/consumer.rs index efa70c6c46..9db54dae04 100644 --- a/crates/router/src/scheduler/consumer.rs +++ b/crates/router/src/scheduler/consumer.rs @@ -7,6 +7,7 @@ use std::{ use error_stack::ResultExt; use futures::future; +use redis_interface::{RedisConnectionPool, RedisEntryId}; use router_env::{tracing, tracing::instrument}; use time::PrimitiveDateTime; use uuid::Uuid; @@ -18,7 +19,7 @@ use super::{ use crate::{ configs::settings, core::errors::{self, CustomResult}, - db::Db, + db::StorageInterface, logger::{error, info}, routes::AppState, scheduler::utils as pt_utils, @@ -89,26 +90,16 @@ pub async fn consumer_operations( let group_created = &mut state .store - .redis_conn - .clone() - .consumer_group_create( - &stream_name, - &group_name, - &redis_interface::RedisEntryId::AfterLastID, - ) + .consumer_group_create(&stream_name, &group_name, &RedisEntryId::AfterLastID) .await; if group_created.is_err() { info!("Consumer group already exists"); } - let mut tasks = fetch_consumer_tasks( - &state.store, - &state.store.redis_conn, - &stream_name, - &group_name, - &consumer_name, - ) - .await?; + let mut tasks = state + .store + .fetch_consumer_tasks(&stream_name, &group_name, &consumer_name) + .await?; let mut handler = vec![]; @@ -133,8 +124,8 @@ pub async fn consumer_operations( #[instrument(skip(db, redis_conn))] pub async fn fetch_consumer_tasks( - db: &dyn Db, - redis_conn: &redis_interface::RedisConnectionPool, + db: &dyn StorageInterface, + redis_conn: &RedisConnectionPool, stream_name: &str, group_name: &str, consumer_name: &str, @@ -196,7 +187,7 @@ pub async fn run_executor<'a>( error!("Failed while handling error"); error!(%error); let status = process - .finish_with_status(&state.store, "GLOBAL_FAILURE".to_string()) + .finish_with_status(&*state.store, "GLOBAL_FAILURE".to_string()) .await; if let Err(err) = status { error!("Failed while performing database operation: GLOBAL_FAILURE"); @@ -222,7 +213,7 @@ pub async fn some_error_handler( "Some error occurred" ); - let db: &dyn Db = &state.store; + let db: &dyn StorageInterface = &*state.store; db.process_tracker_update_process_status_by_ids( vec![process.id], storage::ProcessTrackerUpdate::StatusUpdate { @@ -236,7 +227,7 @@ pub async fn some_error_handler( } pub async fn create_task( - db: &dyn Db, + db: &dyn StorageInterface, process_tracker_entry: storage::ProcessTrackerNew, ) -> CustomResult<(), errors::StorageError> { db.insert_process(process_tracker_entry).await?; diff --git a/crates/router/src/scheduler/producer.rs b/crates/router/src/scheduler/producer.rs index d298e39bcb..a190cf9104 100644 --- a/crates/router/src/scheduler/producer.rs +++ b/crates/router/src/scheduler/producer.rs @@ -8,13 +8,32 @@ use super::metrics; use crate::{ configs::settings::SchedulerSettings, core::errors::{self, CustomResult}, - db::Db, + db::StorageInterface, logger::{debug, error, info, warn}, routes::AppState, scheduler::{utils::*, SchedulerFlow, SchedulerOptions}, types::storage::{self, enums::ProcessTrackerStatus}, }; +//TODO: move to env +pub fn fetch_upper_limit() -> i64 { + 0 +} + +pub fn fetch_lower_limit() -> i64 { + 1800 +} + +pub fn producer_lock_key() -> &'static str { + "PRODUCER_LOCKING_KEY" +} + +pub fn producer_lock_ttl() -> i64 { + // ttl_offset = config.scheduler_lock_offset.or_else(60); + // (scheduler_looper_interval / 100) + (ttl_offset) + 160 //seconds +} + #[instrument(skip_all)] pub async fn start_producer( state: &AppState, @@ -61,18 +80,22 @@ pub async fn run_producer_flow( settings: &SchedulerSettings, ) -> CustomResult<(), errors::ProcessTrackerError> { let tag = "PRODUCER_LOCK"; - let lock_key = &settings.producer.lock_key; + let lock_key = producer_lock_key(); let lock_val = "LOCKED"; let ttl = settings.producer.lock_ttl; // TODO: Pass callback function to acquire_pt_lock() to run after acquiring lock - if acquire_pt_lock(state, tag, lock_key, lock_val, ttl).await { - let tasks = fetch_producer_tasks(&state.store, op, settings).await?; + if state + .store + .acquire_pt_lock(tag, lock_key, lock_val, ttl) + .await + { + let tasks = fetch_producer_tasks(&*state.store, op, settings).await?; debug!("Producer count of tasks {}", tasks.len()); //TODO based on pt.name decide which pt goes to which stream // (LIVE_TRAFFIC_STRM,SCHEDULER_STREAM); array of [(stream,Vec)] divide_and_append_tasks(state, SchedulerFlow::Producer, tasks, settings).await?; - release_pt_lock(&state.store.redis_conn, tag, lock_key).await; + state.store.release_pt_lock(tag, lock_key).await; } Ok(()) @@ -80,7 +103,7 @@ pub async fn run_producer_flow( #[instrument(skip_all)] pub async fn fetch_producer_tasks( - db: &dyn Db, + db: &dyn StorageInterface, _options: &SchedulerOptions, conf: &SchedulerSettings, ) -> CustomResult, errors::ProcessTrackerError> { diff --git a/crates/router/src/scheduler/utils.rs b/crates/router/src/scheduler/utils.rs index b07b4b3c0c..8b70116335 100644 --- a/crates/router/src/scheduler/utils.rs +++ b/crates/router/src/scheduler/utils.rs @@ -4,6 +4,7 @@ use std::{ }; use error_stack::{report, ResultExt}; +use redis_interface::{RedisConnectionPool, RedisEntryId}; use router_env::opentelemetry; use uuid::Uuid; @@ -11,7 +12,6 @@ use super::{consumer, metrics, workflows}; use crate::{ configs::settings::SchedulerSettings, core::errors::{self, CustomResult}, - db::process_tracker::IProcessTracker, logger, routes::AppState, scheduler::{ProcessTrackerBatch, SchedulerFlow}, @@ -19,52 +19,6 @@ use crate::{ utils::{OptionExt, StringExt}, }; -pub async fn acquire_pt_lock( - state: &AppState, - tag: &str, - lock_key: &str, - lock_val: &str, - ttl: i64, -) -> bool { - let conn = state.store.redis_conn.clone(); - let is_lock_acquired = conn.set_key_if_not_exist(lock_key, lock_val).await; - match is_lock_acquired { - Ok(redis_interface::SetNXReply::KeySet) => match conn.set_expiry(lock_key, ttl).await { - Ok(()) => true, - - #[allow(unused_must_use)] - Err(error) => { - logger::error!(error=?error.current_context()); - conn.delete_key(lock_key).await; - false - } - }, - Ok(redis_interface::SetNXReply::KeyNotSet) => { - logger::error!(%tag, "Lock not acquired, previous fetch still in progress"); - false - } - Err(error) => { - logger::error!(error=%error.current_context(), %tag, "Error while locking"); - false - } - } -} - -pub async fn release_pt_lock( - redis_conn: &redis_interface::RedisConnectionPool, - tag: &str, - lock_key: &str, -) -> bool { - let is_lock_released = redis_conn.delete_key(lock_key).await; - match is_lock_released { - Ok(()) => true, - Err(error) => { - logger::error!(error=%error.current_context(), %tag, "Error while releasing lock"); - false - } - } -} - pub async fn divide_and_append_tasks( state: &AppState, flow: SchedulerFlow, @@ -141,12 +95,12 @@ pub async fn update_status_and_append( }?; let field_value_pairs = pt_batch.to_redis_field_value_pairs()?; - let redis_conn = state.store.redis_conn.clone(); - redis_conn + state + .store .stream_append_entry( &pt_batch.stream_name, - &redis_interface::RedisEntryId::AutoGeneratedID, + &RedisEntryId::AutoGeneratedID, field_value_pairs, ) .await @@ -189,7 +143,7 @@ pub fn divide_into_batches( } pub async fn get_batches( - conn: &redis_interface::RedisConnectionPool, + conn: &RedisConnectionPool, stream_name: &str, group_name: &str, consumer_name: &str, @@ -197,7 +151,7 @@ pub async fn get_batches( let response = conn .stream_read_with_options( stream_name, - redis_interface::RedisEntryId::UndeliveredEntryID, + RedisEntryId::UndeliveredEntryID, // Update logic for collecting to Vec and flattening, if count > 1 is provided Some(1), None, diff --git a/crates/router/src/scheduler/workflows/payment_sync.rs b/crates/router/src/scheduler/workflows/payment_sync.rs index 0a9d27bc4e..3a9704087f 100644 --- a/crates/router/src/scheduler/workflows/payment_sync.rs +++ b/crates/router/src/scheduler/workflows/payment_sync.rs @@ -1,15 +1,10 @@ -use std::sync; - -use redis_interface as redis; -use redis_interface::errors as redis_errors; - use super::{PaymentsSyncWorkflow, ProcessTrackerWorkflow}; use crate::{ core::payments::{self as payment_flows, operations}, - db::Db, + db::{get_and_deserialize_key, StorageInterface}, errors, routes::AppState, - scheduler::{consumer, process_data, utils as pt_utils}, + scheduler::{consumer, process_data}, types::{ api, storage::{self, enums}, @@ -24,8 +19,7 @@ impl ProcessTrackerWorkflow for PaymentsSyncWorkflow { state: &'a AppState, process: storage::ProcessTracker, ) -> Result<(), errors::ProcessTrackerError> { - let redis_conn = state.store.redis_conn.clone(); - let db: &dyn Db = &state.store; + let db: &dyn StorageInterface = &*state.store; let tracking_data: api::PaymentsRetrieveRequest = process .tracking_data .clone() @@ -68,7 +62,6 @@ impl ProcessTrackerWorkflow for PaymentsSyncWorkflow { _ => { retry_sync_task( db, - redis_conn, payment_data.payment_attempt.connector, payment_data.payment_attempt.merchant_id, process, @@ -90,24 +83,25 @@ impl ProcessTrackerWorkflow for PaymentsSyncWorkflow { } pub async fn get_sync_process_schedule_time( + db: &dyn StorageInterface, connector: &str, merchant_id: &str, - redis: sync::Arc, retry_count: i32, ) -> Result, errors::ProcessTrackerError> { - let redis_mapping: errors::CustomResult< - process_data::ConnectorPTMapping, - redis_errors::RedisError, - > = redis - .get_and_deserialize_key(&format!("pt_mapping_{}", connector), "ConnectorPTMapping") + let redis_mapping: errors::CustomResult = + get_and_deserialize_key( + db, + &format!("pt_mapping_{}", connector), + "ConnectorPTMapping", + ) .await; let mapping = match redis_mapping { Ok(x) => x, Err(_) => process_data::ConnectorPTMapping::default(), }; - let time_delta = get_sync_schedule_time(mapping, merchant_id, retry_count); + let time_delta = get_sync_schedule_time(mapping, merchant_id, retry_count + 1); - Ok(pt_utils::get_time_from_delta(time_delta)) + Ok(crate::scheduler::utils::get_time_from_delta(time_delta)) } pub fn get_sync_schedule_time( @@ -148,15 +142,13 @@ fn get_delay<'a>( } pub async fn retry_sync_task( - db: &dyn Db, - redis_conn: sync::Arc, + db: &dyn StorageInterface, connector: String, merchant_id: String, pt: storage::ProcessTracker, ) -> Result<(), errors::ProcessTrackerError> { let schedule_time = - get_sync_process_schedule_time(&connector, &merchant_id, redis_conn, pt.retry_count + 1) - .await?; + get_sync_process_schedule_time(db, &connector, &merchant_id, pt.retry_count).await?; match schedule_time { Some(s_time) => pt.retry(db, s_time).await, diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index 654d68004f..310121b956 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -23,10 +23,9 @@ use crate::{ }, payments, }, - db::merchant_account::IMerchantAccount, + db::StorageInterface, logger, routes, routes::AppState, - services::Store, types::{self, api, storage, ErrorResponse, Response}, utils::OptionExt, }; @@ -129,6 +128,7 @@ where response: res.into(), status_code: 200, }; + connector_integration.handle_response(req, response) } payments::CallConnectorAction::Avoid => Ok(router_data), @@ -420,10 +420,10 @@ where { let merchant_account = match api_authentication { ApiAuthentication::Merchant(merchant_auth) => { - authenticate_merchant(request, &state.store, merchant_auth).await? + authenticate_merchant(request, &*state.store, merchant_auth).await? } ApiAuthentication::Connector(connector_auth) => { - authenticate_connector(request, &state.store, connector_auth).await? + authenticate_connector(request, &*state.store, connector_auth).await? } }; logger::debug!(request=?payload); @@ -509,7 +509,7 @@ where pub async fn authenticate_merchant<'a>( request: &HttpRequest, - store: &Store, + store: &dyn StorageInterface, merchant_authentication: MerchantAuthentication<'a>, ) -> RouterResult { match merchant_authentication { @@ -570,7 +570,7 @@ pub async fn authenticate_merchant<'a>( pub async fn authenticate_connector<'a>( _request: &HttpRequest, - store: &Store, + store: &dyn StorageInterface, connector_authentication: ConnectorAuthentication<'a>, ) -> RouterResult { match connector_authentication { @@ -603,7 +603,7 @@ fn get_api_key(req: &HttpRequest) -> RouterResult<&str> { } pub async fn authenticate_by_api_key( - store: &Store, + store: &dyn StorageInterface, api_key: &str, ) -> RouterResult { store @@ -614,7 +614,7 @@ pub async fn authenticate_by_api_key( } async fn authenticate_by_publishable_key( - store: &Store, + store: &dyn StorageInterface, publishable_key: &str, ) -> RouterResult { store diff --git a/crates/router/src/types/api/mandates.rs b/crates/router/src/types/api/mandates.rs index 3fdcf0a365..ec2c3c40d1 100644 --- a/crates/router/src/types/api/mandates.rs +++ b/crates/router/src/types/api/mandates.rs @@ -6,7 +6,6 @@ use crate::{ errors::{self, RouterResult, StorageErrorExt}, payment_methods, }, - db::payment_method::IPaymentMethod, pii::Secret, routes::AppState, types::{api, storage}, @@ -38,7 +37,7 @@ impl MandateResponse { state: &AppState, mandate: storage::Mandate, ) -> RouterResult { - let db = &state.store; + let db = &*state.store; let payment_method = db .find_payment_method(&mandate.payment_method_id) .await diff --git a/crates/router/src/types/api/payment_methods.rs b/crates/router/src/types/api/payment_methods.rs index c5a7b3d0a0..81db81c9ea 100644 --- a/crates/router/src/types/api/payment_methods.rs +++ b/crates/router/src/types/api/payment_methods.rs @@ -1,6 +1,5 @@ use std::collections::HashMap; -use common_utils::custom_serde; use error_stack::report; use literally::hmap; use once_cell::sync::Lazy; @@ -159,7 +158,7 @@ pub struct PaymentMethodResponse { pub installment_payment_enabled: bool, pub payment_experience: Option>, //TODO change it to enum pub metadata: Option, - #[serde(default, with = "custom_serde::iso8601::option")] + #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub created: Option, } @@ -234,7 +233,7 @@ pub struct CustomerPaymentMethod { pub payment_experience: Option>, //TODO change it to enum pub card: Option, pub metadata: Option, - #[serde(default, with = "custom_serde::iso8601::option")] + #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub created: Option, } diff --git a/crates/router/src/types/api/payments.rs b/crates/router/src/types/api/payments.rs index 7a12fb8566..3297fa07a3 100644 --- a/crates/router/src/types/api/payments.rs +++ b/crates/router/src/types/api/payments.rs @@ -1,4 +1,3 @@ -use common_utils::custom_serde; use error_stack::{IntoReport, ResultExt}; use masking::{PeekInterface, Secret}; use router_derive::Setter; @@ -10,6 +9,7 @@ use crate::{ pii, services::api, types::{self, api as api_types, enums, storage}, + utils::custom_serde, }; #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -24,7 +24,7 @@ pub enum PaymentOp { pub struct PaymentsRequest { #[serde( default, - deserialize_with = "crate::utils::custom_serde::payment_id_type::deserialize_option" + deserialize_with = "custom_serde::payment_id_type::deserialize_option" )] pub payment_id: Option, pub merchant_id: Option, @@ -32,7 +32,7 @@ pub struct PaymentsRequest { pub currency: Option, pub capture_method: Option, pub amount_to_capture: Option, - #[serde(default, with = "custom_serde::iso8601::option")] + #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub capture_on: Option, pub confirm: Option, pub customer_id: Option, @@ -50,13 +50,13 @@ pub struct PaymentsRequest { pub payment_token: Option, pub shipping: Option
, pub billing: Option
, - pub browser_info: Option, pub statement_descriptor_name: Option, pub statement_descriptor_suffix: Option, pub metadata: Option, pub client_secret: Option, pub mandate_data: Option, pub mandate_id: Option, + pub browser_info: Option, } impl PaymentsRequest { @@ -93,7 +93,7 @@ pub struct MandateData { #[serde(deny_unknown_fields)] pub struct CustomerAcceptance { pub acceptance_type: AcceptanceType, - #[serde(default, with = "custom_serde::iso8601::option")] + #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub accepted_at: Option, pub online: Option, } @@ -312,7 +312,7 @@ pub struct PaymentsResponse { pub amount_capturable: Option, pub amount_received: Option, pub client_secret: Option>, - #[serde(with = "custom_serde::iso8601::option")] + #[serde(with = "common_utils::custom_serde::iso8601::option")] pub created: Option, pub currency: String, pub customer_id: Option, @@ -322,7 +322,7 @@ pub struct PaymentsResponse { pub mandate_data: Option, pub setup_future_usage: Option, pub off_session: Option, - #[serde(with = "custom_serde::iso8601::option")] + #[serde(with = "common_utils::custom_serde::iso8601::option")] pub capture_on: Option, pub capture_method: Option, #[auth_based] @@ -354,18 +354,18 @@ pub struct PaymentListConstraints { pub ending_before: Option, #[serde(default = "default_limit")] pub limit: i64, - #[serde(default, with = "custom_serde::iso8601::option")] + #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub created: Option, - #[serde(default, with = "custom_serde::iso8601::option")] + #[serde(default, with = "common_utils::custom_serde::iso8601::option")] #[serde(rename = "created.lt")] pub created_lt: Option, - #[serde(default, with = "custom_serde::iso8601::option")] + #[serde(default, with = "common_utils::custom_serde::iso8601::option")] #[serde(rename = "created.gt")] pub created_gt: Option, - #[serde(default, with = "custom_serde::iso8601::option")] + #[serde(default, with = "common_utils::custom_serde::iso8601::option")] #[serde(rename = "created.lte")] pub created_lte: Option, - #[serde(default, with = "custom_serde::iso8601::option")] + #[serde(default, with = "common_utils::custom_serde::iso8601::option")] #[serde(rename = "created.gte")] pub created_gte: Option, } diff --git a/crates/router/src/types/api/webhooks.rs b/crates/router/src/types/api/webhooks.rs index 9fda496869..fe85ec065d 100644 --- a/crates/router/src/types/api/webhooks.rs +++ b/crates/router/src/types/api/webhooks.rs @@ -5,8 +5,8 @@ use time::PrimitiveDateTime; use super::ConnectorCommon; use crate::{ - connection, core::errors::{self, CustomResult}, + db::StorageInterface, services, types::{api, storage::enums}, utils::crypto, @@ -67,8 +67,8 @@ pub trait IncomingWebhook: ConnectorCommon + Sync { async fn get_webhook_body_decoding_merchant_secret( &self, + _db: &dyn StorageInterface, _merchant_id: &str, - _redis_conn: connection::RedisPool, ) -> CustomResult, errors::ConnectorError> { Ok(Vec::new()) } @@ -83,10 +83,10 @@ pub trait IncomingWebhook: ConnectorCommon + Sync { async fn decode_webhook_body( &self, + db: &dyn StorageInterface, headers: &actix_web::http::header::HeaderMap, body: &[u8], merchant_id: &str, - redis_conn: connection::RedisPool, ) -> CustomResult, errors::ConnectorError> { let algorithm = self.get_webhook_body_decoding_algorithm(headers, body)?; @@ -94,7 +94,7 @@ pub trait IncomingWebhook: ConnectorCommon + Sync { .get_webhook_body_decoding_message(headers, body) .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?; let secret = self - .get_webhook_body_decoding_merchant_secret(merchant_id, redis_conn) + .get_webhook_body_decoding_merchant_secret(db, merchant_id) .await .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?; @@ -113,8 +113,8 @@ pub trait IncomingWebhook: ConnectorCommon + Sync { async fn get_webhook_source_verification_merchant_secret( &self, + _db: &dyn StorageInterface, _merchant_id: &str, - _redis_conn: connection::RedisPool, ) -> CustomResult, errors::ConnectorError> { Ok(Vec::new()) } @@ -137,10 +137,10 @@ pub trait IncomingWebhook: ConnectorCommon + Sync { async fn verify_webhook_source( &self, + db: &dyn StorageInterface, headers: &actix_web::http::header::HeaderMap, body: &[u8], merchant_id: &str, - redis_conn: connection::RedisPool, ) -> CustomResult { let algorithm = self .get_webhook_source_verification_algorithm(headers, body) @@ -153,7 +153,7 @@ pub trait IncomingWebhook: ConnectorCommon + Sync { .get_webhook_source_verification_message(headers, body) .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)?; let secret = self - .get_webhook_source_verification_merchant_secret(merchant_id, redis_conn) + .get_webhook_source_verification_merchant_secret(db, merchant_id) .await .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)?; diff --git a/crates/router/src/types/storage.rs b/crates/router/src/types/storage.rs index 85025babb0..12576e3eee 100644 --- a/crates/router/src/types/storage.rs +++ b/crates/router/src/types/storage.rs @@ -12,27 +12,17 @@ pub mod payment_attempt; pub mod payment_intent; pub mod payment_method; pub mod process_tracker; + mod query; pub mod refund; pub mod temp_card; +use diesel_impl::{DieselArray, OptionalDieselArray}; + pub use self::{ - address::*, - configs::*, - connector_response::*, - customers::*, - diesel_impl::{DieselArray, OptionalDieselArray}, - events::*, - locker_mock_up::*, - mandate::*, - merchant_account::*, - merchant_connector_account::*, - payment_attempt::*, - payment_intent::*, - payment_method::*, - process_tracker::*, - refund::*, - temp_card::*, + address::*, configs::*, connector_response::*, customers::*, events::*, locker_mock_up::*, + mandate::*, merchant_account::*, merchant_connector_account::*, payment_attempt::*, + payment_intent::*, payment_method::*, process_tracker::*, refund::*, temp_card::*, }; /// The types and implementations provided by this module are required for the schema generated by @@ -44,6 +34,7 @@ pub use self::{ /// `Option` values. /// /// [diesel-2.0-array-nullability]: https://diesel.rs/guides/migration_guide.html#2-0-0-nullability-of-array-elements + #[doc(hidden)] pub(crate) mod diesel_impl { use diesel::{ diff --git a/crates/router/src/types/storage/address.rs b/crates/router/src/types/storage/address.rs index 683fcc67a9..8a638cdd57 100644 --- a/crates/router/src/types/storage/address.rs +++ b/crates/router/src/types/storage/address.rs @@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize}; use time::{OffsetDateTime, PrimitiveDateTime}; use crate::{consts, schema::address, types::api, utils::generate_id}; + #[derive(Clone, Debug, Deserialize, Serialize, Insertable, router_derive::DebugAsDisplay)] #[diesel(table_name = address)] #[serde(deny_unknown_fields)] @@ -23,7 +24,7 @@ pub struct AddressNew { pub country_code: Option, } -#[derive(Clone, Debug, Identifiable, Queryable, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, Identifiable, Queryable)] #[diesel(table_name = address)] pub struct Address { #[serde(skip_serializing)] diff --git a/crates/router/src/types/storage/configs.rs b/crates/router/src/types/storage/configs.rs index b815fa2c7f..b6c637f441 100644 --- a/crates/router/src/types/storage/configs.rs +++ b/crates/router/src/types/storage/configs.rs @@ -7,13 +7,15 @@ use crate::schema::configs; #[derive(Default, Clone, Debug, Insertable, Serialize, Deserialize)] #[diesel(table_name = configs)] + pub struct ConfigNew { pub key: String, pub config: String, } -#[derive(Default, Clone, Debug, Deserialize, Identifiable, Queryable, Serialize)] +#[derive(Default, Clone, Debug, Identifiable, Queryable, Deserialize, Serialize)] #[diesel(table_name = configs)] + pub struct Config { #[serde(skip_serializing)] pub id: i32, @@ -26,7 +28,7 @@ pub enum ConfigUpdate { Update { config: Option }, } -#[derive(Clone, Debug, Default, AsChangeset)] +#[derive(Clone, Debug, AsChangeset, Default)] #[diesel(table_name = configs)] pub(super) struct ConfigUpdateInternal { config: Option, diff --git a/crates/router/src/types/storage/connector_response.rs b/crates/router/src/types/storage/connector_response.rs index e06d102604..8c0007dc05 100644 --- a/crates/router/src/types/storage/connector_response.rs +++ b/crates/router/src/types/storage/connector_response.rs @@ -19,8 +19,9 @@ pub struct ConnectorResponseNew { pub encoded_data: Option, } -#[derive(Clone, Debug, Identifiable, Queryable, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, Identifiable, Queryable)] #[diesel(table_name = connector_response)] + pub struct ConnectorResponse { #[serde(skip_serializing)] pub id: i32, @@ -35,7 +36,7 @@ pub struct ConnectorResponse { pub encoded_data: Option, } -#[derive(Clone, Debug, AsChangeset, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, AsChangeset, Serialize)] #[diesel(table_name = connector_response)] pub struct ConnectorResponseUpdateInternal { pub connector_transaction_id: Option, diff --git a/crates/router/src/types/storage/customers.rs b/crates/router/src/types/storage/customers.rs index 4da5282f13..0b353830d3 100644 --- a/crates/router/src/types/storage/customers.rs +++ b/crates/router/src/types/storage/customers.rs @@ -13,7 +13,7 @@ use crate::{ }; #[derive( - Default, Clone, Debug, Deserialize, Serialize, Insertable, router_derive::DebugAsDisplay, + Default, Clone, Debug, Insertable, Deserialize, Serialize, router_derive::DebugAsDisplay, )] #[diesel(table_name = customers)] #[serde(deny_unknown_fields)] diff --git a/crates/router/src/types/storage/enums.rs b/crates/router/src/types/storage/enums.rs index 5056dea750..0cb2224ade 100644 --- a/crates/router/src/types/storage/enums.rs +++ b/crates/router/src/types/storage/enums.rs @@ -20,11 +20,11 @@ pub mod diesel_exports { Default, Eq, PartialEq, - router_derive::DieselEnum, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[serde(rename_all = "snake_case")] @@ -61,11 +61,11 @@ pub enum AttemptStatus { Default, Eq, PartialEq, - router_derive::DieselEnum, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[serde(rename_all = "snake_case")] @@ -83,11 +83,11 @@ pub enum AuthenticationType { Default, Eq, PartialEq, - router_derive::DieselEnum, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[serde(rename_all = "snake_case")] @@ -106,11 +106,11 @@ pub enum CaptureMethod { Debug, Eq, PartialEq, - router_derive::DieselEnum, strum::Display, strum::EnumString, serde::Deserialize, serde::Serialize, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[strum(serialize_all = "snake_case")] @@ -141,11 +141,11 @@ pub enum ConnectorType { Eq, Hash, PartialEq, - router_derive::DieselEnum, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] pub enum Currency { @@ -261,11 +261,11 @@ pub enum Currency { Debug, Eq, PartialEq, - router_derive::DieselEnum, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[serde(rename_all = "snake_case")] @@ -280,11 +280,11 @@ pub enum EventClass { Debug, Eq, PartialEq, - router_derive::DieselEnum, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[serde(rename_all = "snake_case")] @@ -299,11 +299,11 @@ pub enum EventObjectType { Debug, Eq, PartialEq, - router_derive::DieselEnum, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[serde(rename_all = "snake_case")] @@ -319,11 +319,11 @@ pub enum EventType { Default, Eq, PartialEq, - router_derive::DieselEnum, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[serde(rename_all = "snake_case")] @@ -347,11 +347,11 @@ pub enum IntentStatus { Default, Eq, PartialEq, - router_derive::DieselEnum, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[serde(rename_all = "snake_case")] @@ -368,11 +368,11 @@ pub enum FutureUsage { Debug, Eq, PartialEq, - router_derive::DieselEnum, strum::Display, strum::EnumString, serde::Serialize, serde::Deserialize, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[strum(serialize_all = "snake_case")] @@ -393,11 +393,11 @@ pub enum PaymentFlow { Eq, Hash, PartialEq, - router_derive::DieselEnum, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[strum(serialize_all = "snake_case")] @@ -422,11 +422,11 @@ pub enum PaymentMethodIssuerCode { Eq, Hash, PartialEq, - router_derive::DieselEnum, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[serde(rename_all = "snake_case")] @@ -448,11 +448,11 @@ pub enum PaymentMethodSubType { Eq, Hash, PartialEq, - router_derive::DieselEnum, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[serde(rename_all = "snake_case")] @@ -478,12 +478,13 @@ pub enum PaymentMethodType { Copy, Debug, Eq, + Hash, PartialEq, - router_derive::DieselEnum, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[serde(rename_all = "lowercase")] @@ -499,11 +500,11 @@ pub enum WalletIssuer { Debug, Eq, PartialEq, - router_derive::DieselEnum, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[serde(rename_all = "snake_case")] @@ -528,9 +529,9 @@ pub enum ProcessTrackerStatus { Default, Eq, PartialEq, - router_derive::DieselEnum, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[strum(serialize_all = "snake_case")] @@ -550,9 +551,9 @@ pub enum RefundStatus { Default, Eq, PartialEq, - router_derive::DieselEnum, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[strum(serialize_all = "snake_case")] @@ -571,13 +572,13 @@ pub enum RefundType { PartialEq, serde::Deserialize, serde::Serialize, - router_derive::DieselEnum, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] -#[router_derive::diesel_enum] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] +#[router_derive::diesel_enum] pub enum RoutingAlgorithm { RoundRobin, MaxConversion, @@ -595,9 +596,9 @@ pub enum RoutingAlgorithm { Default, serde::Deserialize, serde::Serialize, - router_derive::DieselEnum, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[serde(rename_all = "snake_case")] @@ -617,9 +618,9 @@ pub enum MandateType { Default, serde::Deserialize, serde::Serialize, - router_derive::DieselEnum, strum::Display, strum::EnumString, + router_derive::DieselEnum, )] #[router_derive::diesel_enum] #[serde(rename_all = "snake_case")] diff --git a/crates/router/src/types/storage/events.rs b/crates/router/src/types/storage/events.rs index dcb2fccde3..a3a3fa517a 100644 --- a/crates/router/src/types/storage/events.rs +++ b/crates/router/src/types/storage/events.rs @@ -5,7 +5,7 @@ use time::PrimitiveDateTime; use crate::{schema::events, types::storage::enums}; -#[derive(Clone, Debug, Deserialize, Serialize, Insertable, router_derive::DebugAsDisplay)] +#[derive(Clone, Debug, Deserialize, Insertable, Serialize, router_derive::DebugAsDisplay)] #[diesel(table_name = events)] #[serde(deny_unknown_fields)] pub struct EventNew { @@ -18,7 +18,7 @@ pub struct EventNew { pub primary_object_type: enums::EventObjectType, } -#[derive(Clone, Debug, Identifiable, Queryable, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, Identifiable, Queryable)] #[diesel(table_name = events)] pub struct Event { #[serde(skip_serializing)] diff --git a/crates/router/src/types/storage/locker_mock_up.rs b/crates/router/src/types/storage/locker_mock_up.rs index 7f90ac9a32..5df7c60b68 100644 --- a/crates/router/src/types/storage/locker_mock_up.rs +++ b/crates/router/src/types/storage/locker_mock_up.rs @@ -2,7 +2,7 @@ use diesel::{Identifiable, Insertable, Queryable}; use crate::schema::locker_mock_up; -#[derive(Clone, Debug, Eq, PartialEq, Identifiable, Queryable)] +#[derive(Clone, Debug, Eq, Identifiable, Queryable, PartialEq)] #[diesel(table_name = locker_mock_up)] pub struct LockerMockUp { pub id: i32, diff --git a/crates/router/src/types/storage/mandate.rs b/crates/router/src/types/storage/mandate.rs index f9fadc6f3d..f62adc50b2 100644 --- a/crates/router/src/types/storage/mandate.rs +++ b/crates/router/src/types/storage/mandate.rs @@ -1,10 +1,10 @@ use diesel::{AsChangeset, Identifiable, Insertable, Queryable}; use time::PrimitiveDateTime; +use crate::schema::mandate; // use serde::{Deserialize, Serialize}; use crate::{ pii::{self, Secret}, - schema::mandate, types::enums, }; @@ -26,7 +26,7 @@ pub struct Mandate { pub created_at: PrimitiveDateTime, } -#[derive(Clone, Debug, Insertable, Default, router_derive::DebugAsDisplay)] +#[derive(Clone, Debug, Default, Insertable, router_derive::DebugAsDisplay)] #[diesel(table_name = mandate)] pub struct MandateNew { pub mandate_id: String, diff --git a/crates/router/src/types/storage/payment_attempt.rs b/crates/router/src/types/storage/payment_attempt.rs index ef97834dbb..f3dde843d9 100644 --- a/crates/router/src/types/storage/payment_attempt.rs +++ b/crates/router/src/types/storage/payment_attempt.rs @@ -72,7 +72,7 @@ pub struct PaymentAttemptNew { pub browser_info: Option, } -#[derive(Clone, Debug)] +#[derive(Debug, Clone)] pub enum PaymentAttemptUpdate { Update { amount: i32, @@ -234,27 +234,23 @@ impl From for PaymentAttemptUpdateInternal { #[cfg(test)] mod tests { #![allow(clippy::expect_used, clippy::unwrap_used)] + + use uuid::Uuid; + use super::*; - use crate::{ - configs::settings::Settings, db::payment_attempt::IPaymentAttempt, routes, services::Store, - types, - }; + use crate::{configs::settings::Settings, db::StorageImpl, routes, types}; #[actix_rt::test] + #[ignore] async fn test_payment_attempt_insert() { let conf = Settings::new().expect("invalid settings"); - let state = routes::AppState { - flow_name: String::from("default"), - store: Store::new(&conf).await, - conf, - }; - - // let conn = config.conn.get(); + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; + let payment_id = Uuid::new_v4().to_string(); let current_time = common_utils::date_time::now(); let payment_attempt = PaymentAttemptNew { - payment_id: "1".to_string(), + payment_id: payment_id.clone(), connector: types::Connector::Dummy.to_string(), created_at: current_time.into(), modified_at: current_time.into(), @@ -268,24 +264,22 @@ mod tests { .unwrap(); eprintln!("{:?}", response); - assert_eq!(response.payment_id, "1"); + assert_eq!(response.payment_id, payment_id.clone()); } #[actix_rt::test] async fn test_find_payment_attempt() { use crate::configs::settings::Settings; let conf = Settings::new().expect("invalid settings"); + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; - let state = routes::AppState { - flow_name: String::from("default"), - store: Store::new(&conf).await, - conf, - }; let current_time = common_utils::date_time::now(); + let payment_id = Uuid::new_v4().to_string(); + let merchant_id = Uuid::new_v4().to_string(); let payment_attempt = PaymentAttemptNew { - payment_id: "1".to_string(), - merchant_id: "1".to_string(), + payment_id: payment_id.clone(), + merchant_id: merchant_id.clone(), connector: types::Connector::Dummy.to_string(), created_at: current_time.into(), modified_at: current_time.into(), @@ -299,13 +293,13 @@ mod tests { let response = state .store - .find_payment_attempt_by_payment_id_merchant_id("1", "1") + .find_payment_attempt_by_payment_id_merchant_id(&payment_id, &merchant_id) .await .unwrap(); eprintln!("{:?}", response); - assert_eq!(response.payment_id, "1"); + assert_eq!(response.payment_id, payment_id); } #[actix_rt::test] @@ -313,11 +307,7 @@ mod tests { use crate::configs::settings::Settings; let conf = Settings::new().expect("invalid settings"); let uuid = uuid::Uuid::new_v4().to_string(); - let state = routes::AppState { - flow_name: String::from("default"), - store: Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; let current_time = common_utils::date_time::now(); let payment_attempt = PaymentAttemptNew { diff --git a/crates/router/src/types/storage/payment_intent.rs b/crates/router/src/types/storage/payment_intent.rs index 02b2afc1c2..332f2366ff 100644 --- a/crates/router/src/types/storage/payment_intent.rs +++ b/crates/router/src/types/storage/payment_intent.rs @@ -57,7 +57,7 @@ pub struct PaymentIntentNew { pub off_session: Option, } -#[derive(Clone, Debug)] +#[derive(Debug, Clone)] pub enum PaymentIntentUpdate { ResponseUpdate { status: enums::IntentStatus, @@ -94,20 +94,21 @@ pub enum PaymentIntentUpdate { #[derive(Clone, Debug, Default, AsChangeset, router_derive::DebugAsDisplay)] #[diesel(table_name = payment_intent)] -pub(super) struct PaymentIntentUpdateInternal { - amount: Option, - currency: Option, - status: Option, - amount_captured: Option, - customer_id: Option, - return_url: Option, - setup_future_usage: Option, - off_session: Option, - metadata: Option, - client_secret: Option>, - billing_address_id: Option, - shipping_address_id: Option, - modified_at: Option, + +pub struct PaymentIntentUpdateInternal { + pub amount: Option, + pub currency: Option, + pub status: Option, + pub amount_captured: Option, + pub customer_id: Option, + pub return_url: Option, + pub setup_future_usage: Option, + pub off_session: Option, + pub metadata: Option, + pub client_secret: Option>, + pub billing_address_id: Option, + pub shipping_address_id: Option, + pub modified_at: Option, } impl PaymentIntentUpdate { diff --git a/crates/router/src/types/storage/process_tracker.rs b/crates/router/src/types/storage/process_tracker.rs index c7789f9ebd..1b2c22e5ce 100644 --- a/crates/router/src/types/storage/process_tracker.rs +++ b/crates/router/src/types/storage/process_tracker.rs @@ -1,20 +1,21 @@ -#![allow(dead_code)] - use diesel::{AsChangeset, Identifiable, Insertable, Queryable}; use error_stack::ResultExt; use serde::{Deserialize, Serialize}; use time::PrimitiveDateTime; -use crate::{core::errors, db, scheduler::metrics, schema::process_tracker, types::storage::enums}; +use crate::{ + core::errors, db::StorageInterface, scheduler::metrics, schema::process_tracker, + types::storage::enums, +}; #[derive( Clone, Debug, Eq, PartialEq, + Deserialize, Identifiable, Queryable, - Deserialize, Serialize, router_derive::DebugAsDisplay, )] @@ -72,7 +73,7 @@ impl ProcessTracker { pub async fn retry( self, - db: &dyn db::Db, + db: &dyn StorageInterface, schedule_time: PrimitiveDateTime, ) -> Result<(), errors::ProcessTrackerError> { metrics::TASK_RETRIED.add(&metrics::CONTEXT, 1, &[]); @@ -90,7 +91,7 @@ impl ProcessTracker { pub async fn finish_with_status( self, - db: &dyn db::Db, + db: &dyn StorageInterface, status: String, ) -> Result<(), errors::ProcessTrackerError> { db.update_process( @@ -218,6 +219,7 @@ impl From for ProcessTrackerUpdateInternal { // TODO: Move this to a utility module? pub struct Milliseconds(i32); +#[allow(dead_code)] pub struct SchedulerOptions { looper_interval: Milliseconds, db_name: String, @@ -231,6 +233,7 @@ pub struct SchedulerOptions { } #[derive(Debug, Clone)] +#[allow(dead_code)] pub struct ProcessData { db_name: String, cache_name: String, diff --git a/crates/router/src/types/storage/query/customers.rs b/crates/router/src/types/storage/query/customers.rs index d50f8eb654..405781c5f0 100644 --- a/crates/router/src/types/storage/query/customers.rs +++ b/crates/router/src/types/storage/query/customers.rs @@ -11,7 +11,10 @@ use crate::{ impl CustomerNew { #[instrument(skip(conn))] - pub async fn insert(self, conn: &PgPooledConn) -> CustomResult { + pub async fn insert_diesel( + self, + conn: &PgPooledConn, + ) -> CustomResult { generics::generic_insert::<_, _, Customer, _>(conn, self, ExecuteQuery::new()).await } } diff --git a/crates/router/src/types/storage/query/merchant_account.rs b/crates/router/src/types/storage/query/merchant_account.rs index 72956ad777..3a4b3c72bd 100644 --- a/crates/router/src/types/storage/query/merchant_account.rs +++ b/crates/router/src/types/storage/query/merchant_account.rs @@ -13,7 +13,7 @@ use crate::{ impl MerchantAccountNew { #[instrument(skip(conn))] - pub async fn insert( + pub async fn insert_diesel( self, conn: &PgPooledConn, ) -> CustomResult { diff --git a/crates/router/src/types/storage/query/merchant_connector_account.rs b/crates/router/src/types/storage/query/merchant_connector_account.rs index 142f626fcd..5c967cd359 100644 --- a/crates/router/src/types/storage/query/merchant_connector_account.rs +++ b/crates/router/src/types/storage/query/merchant_connector_account.rs @@ -14,7 +14,7 @@ use crate::{ impl MerchantConnectorAccountNew { #[instrument(skip(conn))] - pub async fn insert( + pub async fn insert_diesel( self, conn: &PgPooledConn, ) -> CustomResult { diff --git a/crates/router/src/types/storage/query/payment_attempt.rs b/crates/router/src/types/storage/query/payment_attempt.rs index 37d23bbba1..00c018d865 100644 --- a/crates/router/src/types/storage/query/payment_attempt.rs +++ b/crates/router/src/types/storage/query/payment_attempt.rs @@ -23,7 +23,7 @@ use crate::{ impl PaymentAttemptNew { #[cfg(not(feature = "kv_store"))] #[instrument(skip(conn))] - pub async fn insert( + pub async fn insert_diesel( self, conn: &PgPooledConn, ) -> CustomResult { @@ -32,7 +32,7 @@ impl PaymentAttemptNew { #[cfg(feature = "kv_store")] #[instrument(skip(conn))] - pub async fn insert( + pub async fn insert_diesel( self, conn: &PgPooledConn, ) -> CustomResult { diff --git a/crates/router/src/types/storage/query/payment_intent.rs b/crates/router/src/types/storage/query/payment_intent.rs index 09ced5bc0f..2ca31e5f3c 100644 --- a/crates/router/src/types/storage/query/payment_intent.rs +++ b/crates/router/src/types/storage/query/payment_intent.rs @@ -22,7 +22,7 @@ use crate::{ impl PaymentIntentNew { #[cfg(not(feature = "kv_store"))] #[instrument(skip(conn))] - pub async fn insert( + pub async fn insert_diesel( self, conn: &PgPooledConn, ) -> CustomResult { @@ -31,7 +31,7 @@ impl PaymentIntentNew { #[cfg(feature = "kv_store")] #[instrument(skip(conn))] - pub async fn insert( + pub async fn insert_diesel( self, conn: &PgPooledConn, ) -> CustomResult { diff --git a/crates/router/src/types/storage/query/temp_card.rs b/crates/router/src/types/storage/query/temp_card.rs index 07bb9da5e9..33b1643fa8 100644 --- a/crates/router/src/types/storage/query/temp_card.rs +++ b/crates/router/src/types/storage/query/temp_card.rs @@ -11,7 +11,10 @@ use crate::{ impl TempCardNew { #[instrument(skip(conn))] - pub async fn insert(self, conn: &PgPooledConn) -> CustomResult { + pub async fn insert_diesel( + self, + conn: &PgPooledConn, + ) -> CustomResult { generics::generic_insert::<_, _, TempCard, _>(conn, self, ExecuteQuery::new()).await } } diff --git a/crates/router/src/types/storage/refund.rs b/crates/router/src/types/storage/refund.rs index fbcb65c411..aa002636cb 100644 --- a/crates/router/src/types/storage/refund.rs +++ b/crates/router/src/types/storage/refund.rs @@ -4,7 +4,7 @@ use time::PrimitiveDateTime; use crate::{schema::refund, types::enums}; -#[derive(Clone, Debug, Eq, PartialEq, Identifiable, Queryable)] +#[derive(Clone, Debug, Eq, Identifiable, Queryable, PartialEq)] #[diesel(table_name = refund)] pub struct Refund { pub id: i32, diff --git a/crates/router/src/types/storage/temp_card.rs b/crates/router/src/types/storage/temp_card.rs index 73c125f4e0..6b036ef8d9 100644 --- a/crates/router/src/types/storage/temp_card.rs +++ b/crates/router/src/types/storage/temp_card.rs @@ -4,7 +4,7 @@ use time::PrimitiveDateTime; use crate::schema::temp_card; -#[derive(Queryable, Identifiable, Clone, Debug, Insertable, router_derive::DebugAsDisplay)] +#[derive(Clone, Debug, router_derive::DebugAsDisplay, Queryable, Identifiable, Insertable)] #[diesel(table_name = temp_card)] pub struct TempCard { pub id: i32, diff --git a/crates/router/src/utils.rs b/crates/router/src/utils.rs index c51ada952a..c64b2df699 100644 --- a/crates/router/src/utils.rs +++ b/crates/router/src/utils.rs @@ -5,13 +5,11 @@ mod fp_utils; #[cfg(feature = "kv_store")] pub(crate) mod storage_partitioning; +pub(crate) use common_utils::ext_traits::{ByteSliceExt, BytesExt, Encode, StringExt, ValueExt}; use nanoid::nanoid; pub(crate) use self::{ - ext_traits::{ - validate_address, validate_email, ByteSliceExt, BytesExt, Encode, OptionExt, StringExt, - ValidateCall, ValueExt, - }, + ext_traits::{validate_address, validate_email, OptionExt, ValidateCall}, fp_utils::when, }; use crate::consts; diff --git a/crates/router/src/utils/ext_traits.rs b/crates/router/src/utils/ext_traits.rs index 26dc3dace1..569507c216 100644 --- a/crates/router/src/utils/ext_traits.rs +++ b/crates/router/src/utils/ext_traits.rs @@ -1,4 +1,4 @@ -pub use common_utils::ext_traits::{ByteSliceExt, BytesExt, Encode, StringExt, ValueExt}; +use common_utils::ext_traits::ValueExt; use error_stack::{report, IntoReport, Report, ResultExt}; use once_cell::sync::Lazy; use regex::Regex; @@ -173,8 +173,27 @@ pub fn validate_address(address: &serde_json::Value) -> CustomResult<(), Validat #[cfg(test)] mod tests { + use fake::{faker::internet::en::SafeEmail, Fake}; + use proptest::{ + prop_assert, + strategy::{Just, NewTree, Strategy}, + test_runner::TestRunner, + }; + use super::*; + #[derive(Debug)] + struct ValidEmail; + + impl Strategy for ValidEmail { + type Tree = Just; + type Value = String; + + fn new_tree(&self, _runner: &mut TestRunner) -> NewTree { + Ok(Just(SafeEmail().fake())) + } + } + #[test] fn test_validate_email() { let result = validate_email("abc@example.com"); @@ -186,4 +205,25 @@ mod tests { let result = validate_email(""); assert!(result.is_err()); } + + proptest::proptest! { + /// Example of unit test + #[test] + fn proptest_valid_fake_email(email in ValidEmail) { + prop_assert!(validate_email(&email).is_ok()); + } + + /// Example of unit test + #[test] + fn proptest_invalid_data_email(email in "\\PC*") { + prop_assert!(validate_email(&email).is_err()); + } + + // TODO: make maybe unit test working + // minimal failing input: email = "+@a" + // #[test] + // fn proptest_invalid_email(email in "[.+]@(.+)") { + // prop_assert!(validate_email(&email).is_err()); + // } + } } diff --git a/crates/router/tests/connectors/aci.rs b/crates/router/tests/connectors/aci.rs index b67ecb1766..eaf9e51794 100644 --- a/crates/router/tests/connectors/aci.rs +++ b/crates/router/tests/connectors/aci.rs @@ -5,8 +5,8 @@ use router::{ configs::settings::Settings, connector::aci, core::payments, - routes::AppState, - services, + db::StorageImpl, + routes, services, types::{self, storage::enums, PaymentAddress}, }; @@ -96,11 +96,7 @@ fn construct_refund_router_data() -> types::RefundsRouterData { async fn payments_create_success() { let conf = Settings::new().unwrap(); - let state = AppState { - flow_name: String::from("default"), - store: services::Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; static CV: aci::Aci = aci::Aci; let connector = types::api::ConnectorData { @@ -128,16 +124,12 @@ async fn payments_create_success() { } #[actix_web::test] - +#[ignore] async fn payments_create_failure() { { let conf = Settings::new().unwrap(); static CV: aci::Aci = aci::Aci; - let state = AppState { - flow_name: String::from("default"), - store: services::Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; let connector = types::api::ConnectorData { connector: Box::new(&CV), connector_name: types::Connector::Aci, @@ -178,11 +170,7 @@ async fn refund_for_successful_payments() { connector: Box::new(&CV), connector_name: types::Connector::Aci, }; - let state = AppState { - flow_name: String::from("default"), - store: services::Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; let connector_integration: services::BoxedConnectorIntegration< types::api::Authorize, types::PaymentsAuthorizeData, @@ -229,7 +217,7 @@ async fn refund_for_successful_payments() { } #[actix_web::test] - +#[ignore] async fn refunds_create_failure() { let conf = Settings::new().unwrap(); static CV: aci::Aci = aci::Aci; @@ -237,11 +225,7 @@ async fn refunds_create_failure() { connector: Box::new(&CV), connector_name: types::Connector::Aci, }; - let state = AppState { - flow_name: String::from("default"), - store: services::Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; let connector_integration: services::BoxedConnectorIntegration< types::api::Execute, types::RefundsData, diff --git a/crates/router/tests/connectors/authorizedotnet.rs b/crates/router/tests/connectors/authorizedotnet.rs index 33b3ebe07f..149fd10feb 100644 --- a/crates/router/tests/connectors/authorizedotnet.rs +++ b/crates/router/tests/connectors/authorizedotnet.rs @@ -5,8 +5,8 @@ use router::{ configs::settings::Settings, connector::Authorizedotnet, core::payments, - routes::AppState, - services, + db::StorageImpl, + routes, services, types::{self, storage::enums, PaymentAddress}, }; @@ -95,11 +95,7 @@ fn construct_refund_router_data() -> types::RefundsRouterData { #[ignore] async fn payments_create_success() { let conf = Settings::new().unwrap(); - let state = AppState { - flow_name: String::from("default"), - store: services::Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; static CV: Authorizedotnet = Authorizedotnet; let connector = types::api::ConnectorData { connector: Box::new(&CV), @@ -130,6 +126,7 @@ async fn payments_create_success() { } #[actix_web::test] +#[ignore] async fn payments_create_failure() { { let conf = Settings::new().unwrap(); @@ -138,11 +135,7 @@ async fn payments_create_failure() { connector: Box::new(&CV), connector_name: types::Connector::Authorizedotnet, }; - let state = AppState { - flow_name: String::from("default"), - store: services::Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; let connector_integration: services::BoxedConnectorIntegration< types::api::Authorize, types::PaymentsAuthorizeData, @@ -185,11 +178,7 @@ async fn refunds_create_success() { connector: Box::new(&CV), connector_name: types::Connector::Authorizedotnet, }; - let state = AppState { - flow_name: String::from("default"), - store: services::Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; let connector_integration: services::BoxedConnectorIntegration< types::api::Execute, types::RefundsData, @@ -224,11 +213,7 @@ async fn refunds_create_failure() { connector: Box::new(&CV), connector_name: types::Connector::Authorizedotnet, }; - let state = AppState { - flow_name: String::from("default"), - store: services::Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; let connector_integration: services::BoxedConnectorIntegration< types::api::Execute, types::RefundsData, diff --git a/crates/router/tests/connectors/checkout.rs b/crates/router/tests/connectors/checkout.rs index 1d932d9445..4e1a0c819b 100644 --- a/crates/router/tests/connectors/checkout.rs +++ b/crates/router/tests/connectors/checkout.rs @@ -2,7 +2,8 @@ use std::marker::PhantomData; use router::{ core::payments, - routes::AppState, + db::StorageImpl, + routes, types::{self, api, storage::enums, PaymentAddress}, }; @@ -88,6 +89,7 @@ fn construct_refund_router_data() -> types::RefundsRouterData { } #[actix_web::test] +#[ignore] async fn test_checkout_payment_success() { use router::{configs::settings::Settings, connector::Checkout, services}; @@ -97,11 +99,7 @@ async fn test_checkout_payment_success() { connector: Box::new(&CV), connector_name: types::Connector::Checkout, }; - let state = AppState { - flow_name: String::from("default"), - store: services::Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; let connector_integration: services::BoxedConnectorIntegration< types::api::Authorize, types::PaymentsAuthorizeData, @@ -127,16 +125,13 @@ async fn test_checkout_payment_success() { } #[actix_web::test] +#[ignore] async fn test_checkout_refund_success() { // Successful payment use router::{configs::settings::Settings, connector::Checkout, services}; let conf = Settings::new().expect("invalid settings"); - let state = AppState { - flow_name: String::from("default"), - store: services::Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; static CV: Checkout = Checkout; let connector = types::api::ConnectorData { connector: Box::new(&CV), @@ -201,11 +196,7 @@ async fn test_checkout_payment_failure() { use router::{configs::settings::Settings, connector::Checkout, services}; let conf = Settings::new().expect("invalid settings"); - let state = AppState { - flow_name: String::from("default"), - store: services::Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; static CV: Checkout = Checkout; let connector = types::api::ConnectorData { connector: Box::new(&CV), @@ -231,15 +222,12 @@ async fn test_checkout_payment_failure() { assert!(response.is_err(), "The payment passed"); } #[actix_web::test] +#[ignore] async fn test_checkout_refund_failure() { use router::{configs::settings::Settings, connector::Checkout, services}; let conf = Settings::new().expect("invalid settings"); - let state = AppState { - flow_name: String::from("default"), - store: services::Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; static CV: Checkout = Checkout; let connector = types::api::ConnectorData { connector: Box::new(&CV), diff --git a/crates/router/tests/customers.rs b/crates/router/tests/customers.rs index 26af9e96d1..ce7f6b5f79 100644 --- a/crates/router/tests/customers.rs +++ b/crates/router/tests/customers.rs @@ -5,6 +5,7 @@ mod utils; // When test-connector feature is enabled, you can pass the connector name in description #[actix_web::test] +#[ignore] // verify the API-KEY/merchant id has stripe as first choice async fn customer_success() { utils::setup().await; @@ -73,6 +74,7 @@ async fn customer_success() { } #[actix_web::test] +#[ignore] // verify the API-KEY/merchant id has stripe as first choice async fn customer_failure() { utils::setup().await; diff --git a/crates/router/tests/health_check.rs b/crates/router/tests/health_check.rs index 0679767af1..89d506eff5 100644 --- a/crates/router/tests/health_check.rs +++ b/crates/router/tests/health_check.rs @@ -1,25 +1,11 @@ mod utils; +use utils::{mk_service, AppClient}; + #[actix_web::test] async fn health_check() { - utils::setup().await; - let client = awc::Client::default(); + let server = mk_service().await; + let client = AppClient::guest(); - let response = client - .get("http://127.0.0.1:8080/health") - .send() - .await - .unwrap(); - println!("{:?}", response); - assert_eq!(response.status(), awc::http::StatusCode::OK) -} - -#[actix_web::test] -async fn health_check_root() { - utils::setup().await; - let client = awc::Client::default(); - - let response = client.get("http://127.0.0.1:8080/").send().await.unwrap(); - println!("{:?}", response); - // assert_eq!(response.status(), awc::http::StatusCode::OK) + assert_eq!(client.health(&server).await, "health is good"); } diff --git a/crates/router/tests/integration_demo.rs b/crates/router/tests/integration_demo.rs index 03478d4935..d05e619760 100644 --- a/crates/router/tests/integration_demo.rs +++ b/crates/router/tests/integration_demo.rs @@ -1,366 +1,249 @@ -use http::StatusCode; -use reqwest::Client; -use router::{configs::settings::Settings, services::Store, types::storage::AddressNew}; -use serde_json::Value; - mod utils; -struct TestApp { - store: Store, + +#[allow(dead_code)] +mod auth { + include!("connectors/connector_auth.rs"); } -impl TestApp { - pub async fn init() -> (Client, TestApp) { - utils::setup().await; +use auth::ConnectorAuthentication; +use utils::{mk_service, ApiKey, AppClient, LegacyAppClient, MerchantId, PaymentId, Status}; - let client = Client::new(); - let conf = Settings::new().unwrap(); - let store = Store::new(&conf).await; - let app = TestApp { store }; +/// Example of unit test +/// 1) Create Merchant account +#[actix_web::test] +async fn create_merchant_account() { + let server = mk_service().await; + let client = AppClient::guest(); + let admin_client = client.admin("test_admin"); - (client, app) - } + let expected = "merchant_12345"; + let hlist_pat![merchant_id, _api_key]: HList![MerchantId, ApiKey] = admin_client + .create_merchant_account(&server, expected.to_owned()) + .await; + + assert_eq!(expected, *merchant_id); } -fn mk_merchant_account() -> serde_json::Value { - let timestamp = common_utils::date_time::now(); +/// Example of unit test +/// ```pseudocode +/// mk_service = +/// app_state <- AppState(StorageImpl::Mock) // Instantiate a mock database to simulate real world SQL database. +/// actix_web::test::init_service(<..>) // Initialize service from application builder instance . +/// ``` +/// ### Tests with mocks are typically structured like so: +/// 1) create mock objects and specify what values they return +/// 2) run code under test, passing mock objects to it +/// 3) assert mocks were called the expected number of times, with the expected arguments +/// ``` +/// fn show_users(get_users: impl FnOnce() -> Vec<&'static str>) -> String { +/// get_users().join(", ") +/// } +/// // GIVEN[1]: +/// let get_users = || vec!["Andrey", "Alisa"]; +/// // WHEN[2]: +/// let list_users = show_users(get_users); +/// // THEN[3]: +/// assert_eq!(list_users, "Andrey, Alisa"); +/// ``` +/// ### Test case +/// 1) Create Merchant account (Get the API key) +/// 2) Create a connector +/// 3) Create a payment for 100 USD +/// 4) Confirm a payment (let it get processed through Stripe) +/// 5) Refund for 50USD success +/// 6) Another refund for 50USD success +/// +/// ### Useful resources +/// * +/// * +/// * +#[actix_web::test] +async fn partial_refund() { + let authentication = ConnectorAuthentication::new(); + let server = mk_service().await; - serde_json::json!({ - "merchant_id": format!("merchant_{timestamp}"), - "merchant_name": "NewAge Retailer", - "merchant_details": { - "primary_contact_person": "John Test", - "primary_email": "JohnTest@test.com", - "primary_phone": "sunt laborum", - "secondary_contact_person": "John Test2", - "secondary_email": "JohnTest2@test.com", - "secondary_phone": "cillum do dolor id", - "website": "www.example.com", - "about_business": "Online Retail with a wide selection of organic products for North America", - "address": { - "line1": "Juspay Router", - "line2": "Koramangala", - "line3": "Stallion", - "city": "Bangalore", - "state": "Karnataka", - "zip": "560095", - "country": "IN" - } - }, - "return_url": "www.example.com/success", - "webhook_details": { - "webhook_version": "1.0.1", - "webhook_username": "ekart_retail", - "webhook_password": "password_ekart@123", - "payment_created_enabled": true, - "payment_succeeded_enabled": true, - "payment_failed_enabled": true - }, - "routing_algorithm": "custom", - "custom_routing_rules": [ - { - "payment_methods_incl": [ - "card", - "card" - ], - "payment_methods_excl": [ - "card", - "card" - ], - "payment_method_types_incl": [ - "credit", - "credit" - ], - "payment_method_types_excl": [ - "credit", - "credit" - ], - "payment_method_issuers_incl": [ - "Citibank", - "JPMorgan" - ], - "payment_method_issuers_excl": [ - "Citibank", - "JPMorgan" - ], - "countries_incl": [ - "US", - "UK", - "IN" - ], - "countries_excl": [ - "US", - "UK", - "IN" - ], - "currencies_incl": [ - "USD", - "EUR" - ], - "currencies_excl": [ - "AED", - "SGD" - ], - "metadata_filters_keys": [ - "payments.udf1", - "payments.udf2" - ], - "metadata_filters_values": [ - "android", - "Category_Electronics" - ], - "connectors_pecking_order": [ + let client = AppClient::guest(); + let admin_client = client.admin("test_admin"); + + let hlist_pat![merchant_id, api_key]: HList![MerchantId, ApiKey] = + admin_client.create_merchant_account(&server, None).await; + + let _connector: serde_json::Value = admin_client + .create_connector( + &server, + &merchant_id, "stripe", - "adyen", - "brain_tree" - ], - "connectors_traffic_weightage_key": [ - "stripe", - "adyen", - "brain_tree" - ], - "connectors_traffic_weightage_value": [ - 50, - 30, - 20 - ] - }, - { - "payment_methods_incl": [ - "card", - "card" - ], - "payment_methods_excl": [ - "card", - "card" - ], - "payment_method_types_incl": [ - "credit", - "credit" - ], - "payment_method_types_excl": [ - "credit", - "credit" - ], - "payment_method_issuers_incl": [ - "Citibank", - "JPMorgan" - ], - "payment_method_issuers_excl": [ - "Citibank", - "JPMorgan" - ], - "countries_incl": [ - "US", - "UK", - "IN" - ], - "countries_excl": [ - "US", - "UK", - "IN" - ], - "currencies_incl": [ - "USD", - "EUR" - ], - "currencies_excl": [ - "AED", - "SGD" - ], - "metadata_filters_keys": [ - "payments.udf1", - "payments.udf2" - ], - "metadata_filters_values": [ - "android", - "Category_Electronics" - ], - "connectors_pecking_order": [ - "stripe", - "adyen", - "brain_tree" - ], - "connectors_traffic_weightage_key": [ - "stripe", - "adyen", - "brain_tree" - ], - "connectors_traffic_weightage_value": [ - 50, - 30, - 20 - ] - } - ], - "sub_merchants_enabled": false, - "metadata": { - "city": "NY", - "unit": "245" - } - }) + &authentication.checkout.unwrap().api_key, + ) + .await; + + let user_client = client.user(&api_key); + let hlist_pat![payment_id]: HList![PaymentId] = + user_client.create_payment(&server, 100, 100).await; + + let hlist_pat![status]: HList![Status] = + user_client.create_refund(&server, &payment_id, 50).await; + assert_eq!(&*status, "pending"); + + let hlist_pat![status]: HList![Status] = + user_client.create_refund(&server, &payment_id, 50).await; + assert_eq!(&*status, "pending"); } -fn mk_payment() -> serde_json::Value { - serde_json::json!({ - "amount": 6540, - "currency": "USD", - "confirm": true, - "capture_method": "automatic", - "capture_on": "2022-09-10T10:11:12Z", - "amount_to_capture": 6540, - "customer_id": "cus_udst2tfldj6upmye2reztkmm4i", - "email": "guest@example.com", - "name": "John Doe", - "phone": "999999999", - "phone_country_code": "+65", - "description": "Its my first payment request", - "authentication_type": "no_three_ds", - "payment_method": "card", - "payment_method_data": { - "card": { - "card_number": "4242424242424242", - "card_exp_month": "10", - "card_exp_year": "35", - "card_holder_name": "John Doe", - "card_cvc": "123" - } - }, - "statement_descriptor_name": "Juspay", - "statement_descriptor_suffix": "Router", - "metadata": { - "udf1": "value1", - "new_customer": "true", - "login_date": "2019-09-10T10:11:12Z" - } - }) -} +/// Example of unit test +/// ```pseudocode +/// mk_service = +/// app_state <- AppState(StorageImpl::Mock) // Instantiate a mock database to simulate real world SQL database. +/// actix_web::test::init_service(<..>) // Initialize service from application builder instance . +/// ``` +/// ### Tests with mocks are typically structured like so: +/// 1) create mock objects and specify what values they return +/// 2) run code under test, passing mock objects to it +/// 3) assert mocks were called the expected number of times, with the expected arguments +/// ``` +/// fn show_users(get_users: impl FnOnce() -> Vec<&'static str>) -> String { +/// get_users().join(", ") +/// } +/// // GIVEN[1]: +/// let get_users = || vec!["Andrey", "Alisa"]; +/// // WHEN[2]: +/// let list_users = show_users(get_users); +/// // THEN[3]: +/// assert_eq!(list_users, "Andrey, Alisa"); +/// ``` +/// Test case +/// 1) Create a payment for 100 USD +/// 2) Confirm a payment (let it get processed through Stripe) +/// 3) Refund for 50USD successfully +/// 4) Try another refund for 100USD +/// 5) Get an error for second refund +/// +/// ### Useful resources +/// * +/// * +/// * +#[actix_web::test] +async fn exceed_refund() { + let authentication = ConnectorAuthentication::new(); + let server = mk_service().await; -fn mk_connector() -> serde_json::Value { - serde_json::json!({ - "merchant_id": "y3oqhf46pyzuxjbcn2giaqnb44", - "connector_type": "payment_processor", - "connector_name": "stripe", - "connector_account_details": { - "api_key": "Basic MyVerySecretApiKey" - }, - "test_mode": false, - "disabled": false, - "payment_methods_enabled": [ - { - "payment_method": "card", - "payment_method_types": [ - "credit_card" - ], - "payment_method_issuers": [ - [ - "HDFC" - ] - ], - "payment_schemes": [ - "VISA" - ], - "accepted_currencies": [ - "USD" - ], - "accepted_countries": [ - "US" - ], - "minimum_amount": 1, - "maximum_amount": null, - "recurring_enabled": true, - "installment_payment_enabled": true, - "payment_experience": [ - "redirect_to_url" - ] - } - ], - "metadata": { - "city": "NY", - "unit": "245" - } - }) + let client = AppClient::guest(); + let admin_client = client.admin("test_admin"); + + let hlist_pat![merchant_id, api_key]: HList![MerchantId, ApiKey] = + admin_client.create_merchant_account(&server, None).await; + + let _connector: serde_json::Value = admin_client + .create_connector( + &server, + &merchant_id, + "stripe", + &authentication.checkout.unwrap().api_key, + ) + .await; + + let user_client = client.user(&api_key); + + let hlist_pat![payment_id]: HList![PaymentId] = + user_client.create_payment(&server, 100, 100).await; + + let hlist_pat![status]: HList![Status] = + user_client.create_refund(&server, &payment_id, 50).await; + assert_eq!(&*status, "pending"); + + let message: serde_json::Value = user_client.create_refund(&server, &payment_id, 100).await; + assert_eq!( + message["error"]["message"], + "Refund amount exceeds the payment amount." + ); } #[actix_web::test] -async fn create_payment() { - let (client, _) = TestApp::init().await; +#[ignore] +async fn legacy_partial_refund() { + legacy_setup().await; - let merchant_account = client - .post("http://localhost:8080/accounts") - .header("api-key", "test_admin") - .json(&mk_merchant_account()) - .send() - .await - .unwrap() - .json::() - .await - .unwrap(); + let authentication = ConnectorAuthentication::new(); + let dummy_client = LegacyAppClient::dummy(); + let admin_client = dummy_client.admin("test_admin"); - println!("{:?}", merchant_account); + let hlist_pat![merchant_id, api_key] = admin_client + .create_merchant_account::(None) + .await; - let merchant_id = merchant_account - .get("merchant_id") - .and_then(Value::as_str) - .unwrap(); + let _connector = admin_client + .create_connector::( + &merchant_id, + "stripe", + &authentication.checkout.unwrap().api_key, + ) + .await; - let api_key = merchant_account - .get("api_key") - .and_then(Value::as_str) - .unwrap(); + let user_client = dummy_client.user(&api_key); + let hlist_pat![payment_id] = user_client + .create_payment::(100, 100) + .await; - let _connector = client - .post(format!( - "http://localhost:8080/account/{merchant_id}/connectors" - )) - .json(&mk_connector()) - .send() - .await - .unwrap() - .json::(); + let hlist_pat![status] = user_client + .create_refund::(&payment_id, 50) + .await; + assert_eq!(&*status, "succeeded"); - let payment = client - .post("http://localhost:8080/payments") - .header("api-key", api_key) - .json(&mk_payment()) - .send() - .await - .unwrap() - .json::() - .await - .unwrap(); + let hlist_pat![status] = user_client + .create_refund::(&payment_id, 50) + .await; + assert_eq!(&*status, "succeeded"); +} - println!("{payment}"); +async fn legacy_setup() { + utils::setup().await; } #[actix_web::test] -async fn address() { - use router::db::address::IAddress; +#[ignore] +async fn legacy_exceed_refund() { + legacy_setup().await; - let (_, app) = TestApp::init().await; - let store = app.store; + let authentication = ConnectorAuthentication::new(); + let dummy_client = LegacyAppClient::dummy(); + let admin_client = dummy_client.admin("test_admin"); - let address = store - .insert_address(AddressNew { - city: "City!".to_owned().into(), - ..AddressNew::default() - }) - .await - .unwrap(); + let hlist_pat![merchant_id, api_key] = admin_client + .create_merchant_account::(None) + .await; - let address = store.find_address(&address.address_id).await.unwrap(); + let _connector = admin_client + .create_connector::( + &merchant_id, + "stripe", + &authentication.checkout.unwrap().api_key, + ) + .await; - assert_eq!(address.city, Some("City!".to_owned())); + let user_client = dummy_client.user(&api_key); + let hlist_pat![payment_id] = user_client + .create_payment::(100, 100) + .await; + + let hlist_pat![status] = user_client + .create_refund::(&payment_id, 50) + .await; + assert_eq!(&*status, "succeeded"); + + let message = user_client + .create_refund::(&payment_id, 100) + .await; + assert_eq!( + message["error"]["message"], + "Refund amount exceeds the payment amount." + ); } #[actix_web::test] -async fn health() { - let (client, _) = TestApp::init().await; +#[ignore] +async fn legacy_health_check() { + legacy_setup().await; - let n = client - .get("http://localhost:8080/health") - .send() - .await - .unwrap(); - - assert_eq!(n.status(), StatusCode::OK); + let dummy_client = LegacyAppClient::dummy(); + assert_eq!(dummy_client.health().await, "health is good"); } diff --git a/crates/router/tests/payments.rs b/crates/router/tests/payments.rs index acbfd3ee70..dc543c5755 100644 --- a/crates/router/tests/payments.rs +++ b/crates/router/tests/payments.rs @@ -5,6 +5,7 @@ mod utils; use router::{ configs, core::payments, + db::StorageImpl, routes, services, types::{self, api, storage::enums}, }; @@ -155,6 +156,7 @@ async fn payments_create_adyen() { #[actix_web::test] // verify the API-KEY/merchant id has stripe as first choice +#[ignore] async fn payments_create_fail() { utils::setup().await; @@ -269,13 +271,9 @@ async fn payments_create_core() { use configs::settings::Settings; let conf = Settings::new().expect("invalid settings"); - let state = routes::AppState { - flow_name: String::from("default"), - store: services::Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; - let mut merchant_account = services::authenticate_by_api_key(&state.store, "MySecretApiKey") + let mut merchant_account = services::authenticate_by_api_key(&*state.store, "MySecretApiKey") .await .unwrap(); merchant_account.custom_routing_rules = Some(serde_json::json!([ @@ -426,17 +424,13 @@ async fn payments_create_core_adyen_no_redirect() { use crate::configs::settings::Settings; let conf = Settings::new().expect("invalid settings"); - let state = routes::AppState { - flow_name: String::from("default"), - store: services::Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; let customer_id = format!("cust_{}", Uuid::new_v4()); let merchant_id = "arunraj".to_string(); let payment_id = "pay_mbabizu24mvu3mela5njyhpit10".to_string(); - let mut merchant_account = services::authenticate_by_api_key(&state.store, "321") + let mut merchant_account = services::authenticate_by_api_key(&*state.store, "321") .await .unwrap(); merchant_account.custom_routing_rules = Some(serde_json::json!([ diff --git a/crates/router/tests/payments2.rs b/crates/router/tests/payments2.rs index 09aac122fd..1bdb30aced 100644 --- a/crates/router/tests/payments2.rs +++ b/crates/router/tests/payments2.rs @@ -4,6 +4,7 @@ mod utils; use router::{ core::payments, + db::StorageImpl, types::{api, storage::enums}, *, }; @@ -34,13 +35,9 @@ async fn payments_create_core() { use router::configs::settings::Settings; let conf = Settings::new().expect("invalid settings"); - let state = routes::AppState { - flow_name: String::from("default"), - store: services::Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; - let mut merchant_account = services::authenticate_by_api_key(&state.store, "MySecretApiKey") + let mut merchant_account = services::authenticate_by_api_key(&*state.store, "MySecretApiKey") .await .unwrap(); merchant_account.custom_routing_rules = Some(serde_json::json!([ @@ -83,15 +80,7 @@ async fn payments_create_core() { }), statement_descriptor_name: Some("Juspay".to_string()), statement_descriptor_suffix: Some("Router".to_string()), - payment_token: None, - phone: None, - phone_country_code: None, - metadata: None, - mandate_data: None, - mandate_id: None, - off_session: None, - client_secret: None, - browser_info: None, + ..<_>::default() }; let expected_response = api::PaymentsResponse { @@ -145,18 +134,18 @@ async fn payments_create_core() { // ..api::CreateCustomerRequest::default() // }; // -// let _customer = customer_data.insert(&state.store).await.unwrap(); +// let _customer = customer_data.insert(&*state.store).await.unwrap(); // // let merchant_account = services::authenticate(&state, "123").await.unwrap(); // let payment_attempt = storage::PaymentAttempt::find_by_payment_id_merchant_id( -// &state.store, +// &*state.store, // &payment_id, // &merchant_id, // ) // .await // .unwrap(); // let payment_intent = storage::PaymentIntent::find_by_payment_id_merchant_id( -// &state.store, +// &*state.store, // &payment_id, // &merchant_id, // ) @@ -167,7 +156,7 @@ async fn payments_create_core() { // status: None, // }; // payment_intent -// .update(&state.store, payment_intent_update) +// .update(&*state.store, payment_intent_update) // .await // .unwrap(); // @@ -197,17 +186,13 @@ async fn payments_create_core_adyen_no_redirect() { use router::configs::settings::Settings; let conf = Settings::new().expect("invalid settings"); - let state = routes::AppState { - flow_name: String::from("default"), - store: services::Store::new(&conf).await, - conf, - }; + let state = routes::AppState::with_storage(conf, StorageImpl::DieselPostgresqlTest).await; let customer_id = format!("cust_{}", Uuid::new_v4()); let merchant_id = "arunraj".to_string(); let payment_id = "pay_mbabizu24mvu3mela5njyhpit10".to_string(); - let merchant_account = services::authenticate_by_api_key(&state.store, "321") + let merchant_account = services::authenticate_by_api_key(&*state.store, "321") .await .unwrap(); diff --git a/crates/router/tests/refunds.rs b/crates/router/tests/refunds.rs index 40501309c2..7eff4f2e9b 100644 --- a/crates/router/tests/refunds.rs +++ b/crates/router/tests/refunds.rs @@ -1,3 +1,5 @@ +use utils::{mk_service, AppClient}; + mod utils; // setting the connector in environment variables doesn't work when run in parallel. Neither does passing the paymentid @@ -7,61 +9,29 @@ mod utils; #[actix_web::test] // verify the API-KEY/merchant id has stripe as first choice async fn refund_create_fail_stripe() { - utils::setup().await; + let app = mk_service().await; + let client = AppClient::guest(); + + let user_client = client.user("321"); let payment_id = format!("test_{}", uuid::Uuid::new_v4()); - let api_key = ("API-KEY", "MySecretApiKey"); + let refund: serde_json::Value = user_client.create_refund(&app, &payment_id, 10).await; - let refund_req = serde_json::json!({ - "amount" : 10.00, - "currency" : "USD", - "refund_id" : "refund_123", - "payment_id" : payment_id, - "merchant_id" : "jarnura", - }); - - let client = awc::Client::default(); - - let mut refund_response = client - .post("http://127.0.0.1:8080/refunds/create") - .insert_header(api_key) - .send_json(&refund_req) - .await - .unwrap(); - - let refund_response_body = refund_response.body().await; - println!("{:?} =:= {:?}", refund_response, refund_response_body); - assert_eq!(refund_response.status(), awc::http::StatusCode::BAD_REQUEST); + assert_eq!(refund["error"]["message"], "Access forbidden, invalid API key was used. Please create your new API key from the Dashboard Settings section."); } #[actix_web::test] // verify the API-KEY/merchant id has adyen as first choice async fn refund_create_fail_adyen() { - utils::setup().await; + let app = mk_service().await; + let client = AppClient::guest(); + + let user_client = client.user("321"); let payment_id = format!("test_{}", uuid::Uuid::new_v4()); - let api_key = ("API-KEY", "321"); + let refund: serde_json::Value = user_client.create_refund(&app, &payment_id, 10).await; - let refund_req = serde_json::json!({ - "amount" : 10.00, - "currency" : "USD", - "refund_id" : "refund_123", - "payment_id" : payment_id, - "merchant_id" : "jarnura", - }); - - let client = awc::Client::default(); - - let mut refund_response = client - .post("http://127.0.0.1:8080/refunds/create") - .insert_header(api_key) - .send_json(&refund_req) - .await - .unwrap(); - - let refund_response_body = refund_response.body().await; - println!("{:?} =:= {:?}", refund_response, refund_response_body); - assert_eq!(refund_response.status(), awc::http::StatusCode::BAD_REQUEST); + assert_eq!(refund["error"]["message"], "Access forbidden, invalid API key was used. Please create your new API key from the Dashboard Settings section."); } #[actix_web::test] diff --git a/crates/router/tests/utils.rs b/crates/router/tests/utils.rs index 9505a55e18..93a7f4b50c 100644 --- a/crates/router/tests/utils.rs +++ b/crates/router/tests/utils.rs @@ -1,5 +1,14 @@ #![allow(dead_code)] -use router::{configs::settings::Settings, start_server}; +use actix_http::{body::MessageBody, Request}; +use actix_web::{ + dev::{Service, ServiceResponse}, + test::{call_and_read_body_json, TestRequest}, +}; +use derive_deref::Deref; +use reqwest::{Client, RequestBuilder}; +use router::{configs::settings::Settings, routes::AppState, start_server}; +use serde::{de::DeserializeOwned, Deserialize}; +use serde_json::{json, Value}; use tokio::sync::OnceCell; static SERVER: OnceCell = OnceCell::const_new(); @@ -15,3 +24,639 @@ async fn spawn_server() -> bool { pub async fn setup() { SERVER.get_or_init(spawn_server).await; } + +const STRIPE_MOCK: &str = "http://localhost:12111/"; + +async fn stripemock() -> Option { + // not working: https://github.com/stripe/stripe-mock/issues/231 + None +} + +pub async fn mk_service() -> impl actix_web::dev::Service< + actix_http::Request, + Response = actix_web::dev::ServiceResponse, + Error = actix_web::Error, +> { + let mut conf = Settings::new().unwrap(); + let request_body_limit = conf.server.request_body_limit; + + if let Some(url) = stripemock().await { + conf.connectors.stripe.base_url = url; + } + + let app_state = AppState::with_storage(conf, router::db::StorageImpl::Mock).await; + actix_web::test::init_service(router::mk_app(app_state, request_body_limit)).await +} + +pub struct Guest; + +pub struct Admin { + authkey: String, +} + +pub struct User { + authkey: String, +} + +pub struct LegacyAppClient { + client: Client, + state: T, +} + +impl LegacyAppClient { + pub fn dummy() -> LegacyAppClient { + LegacyAppClient { + client: Client::new(), + state: Guest, + } + } +} + +impl LegacyAppClient { + pub fn admin(&self, authkey: &str) -> LegacyAppClient { + LegacyAppClient { + client: self.client.clone(), + state: Admin { + authkey: authkey.to_string(), + }, + } + } + + pub fn url(&self, path: &str) -> String { + if path.starts_with('/') { + format!("http://localhost:8080{}", path) + } else { + format!("http://localhost:8080/{}", path) + } + } + + pub fn get(&self, path: impl AsRef) -> RequestBuilder { + self.client.get(self.url(path.as_ref())) + } + + pub fn post(&self, path: impl AsRef) -> RequestBuilder { + self.client.post(self.url(path.as_ref())) + } + + pub fn user(&self, authkey: &str) -> LegacyAppClient { + LegacyAppClient { + client: self.client.clone(), + state: User { + authkey: authkey.to_string(), + }, + } + } + + pub async fn health(&self) -> String { + self.get("health") + .send() + .await + .unwrap() + .text() + .await + .unwrap() + } +} + +impl LegacyAppClient { + #[track_caller] + pub async fn create_merchant_account( + &self, + merchant_id: impl Into>, + ) -> T { + self.post("accounts") + .header("api-key", &self.state.authkey) + .json(&mk_merchant_account(merchant_id.into())) + .send() + .await + .unwrap() + .json::() + .await + .unwrap() + } + + #[track_caller] + pub async fn create_connector( + &self, + merchant_id: &str, + connector_name: &str, + api_key: &str, + ) -> T { + self.post(format!("account/{merchant_id}/connectors")) + .header("api-key", &self.state.authkey) + .json(&mk_connector(connector_name, api_key)) + .send() + .await + .unwrap() + .json::() + .await + .unwrap() + } +} + +impl LegacyAppClient { + #[track_caller] + pub async fn create_payment( + &self, + amount: i32, + amount_to_capture: i32, + ) -> T { + self.post("payments") + .header("api-key", &self.state.authkey) + .json(&mk_payment(amount, amount_to_capture)) + .send() + .await + .unwrap() + .json::() + .await + .unwrap() + } + + #[track_caller] + pub async fn create_refund(&self, payment_id: &str, amount: usize) -> T { + self.post("refunds") + .header("api-key", &self.state.authkey) + .json(&mk_refund(payment_id, amount)) + .send() + .await + .unwrap() + .json::() + .await + .unwrap() + } +} + +#[allow(dead_code)] +pub struct AppClient { + state: T, +} + +impl AppClient { + pub fn guest() -> AppClient { + AppClient { state: Guest } + } +} + +impl AppClient { + pub async fn create_merchant_account( + &self, + app: &S, + merchant_id: impl Into>, + ) -> T + where + S: Service, Error = actix_web::Error>, + B: MessageBody, + { + let request = TestRequest::post() + .uri("/accounts") + .append_header(("api-key".to_owned(), self.state.authkey.clone())) + .set_json(mk_merchant_account(merchant_id.into())) + .to_request(); + + call_and_read_body_json(app, request).await + } + + pub async fn create_connector( + &self, + app: &S, + merchant_id: &str, + connector_name: &str, + api_key: &str, + ) -> T + where + S: Service, Error = actix_web::Error>, + B: MessageBody, + { + let request = TestRequest::post() + .uri(&format!("/account/{merchant_id}/connectors")) + .append_header(("api-key".to_owned(), self.state.authkey.clone())) + .set_json(mk_connector(connector_name, api_key)) + .to_request(); + + call_and_read_body_json(app, request).await + } +} + +impl AppClient { + pub async fn create_payment( + &self, + app: &S, + amount: i32, + amount_to_capture: i32, + ) -> T + where + S: Service, Error = actix_web::Error>, + B: MessageBody, + { + let request = TestRequest::post() + .uri("/payments") + .append_header(("api-key".to_owned(), self.state.authkey.clone())) + .set_json(mk_payment(amount, amount_to_capture)) + .to_request(); + call_and_read_body_json(app, request).await + } + + pub async fn create_refund( + &self, + app: &S, + payment_id: &str, + amount: usize, + ) -> T + where + S: Service, Error = actix_web::Error>, + B: MessageBody, + { + let request = TestRequest::post() + .uri("/refunds") + .append_header(("api-key".to_owned(), self.state.authkey.clone())) + .set_json(mk_refund(payment_id, amount)) + .to_request(); + call_and_read_body_json(app, request).await + } +} + +impl AppClient { + pub fn admin(&self, authkey: &str) -> AppClient { + AppClient { + state: Admin { + authkey: authkey.to_string(), + }, + } + } + + pub fn user(&self, authkey: &str) -> AppClient { + AppClient { + state: User { + authkey: authkey.to_string(), + }, + } + } + + pub async fn health(&self, app: &S) -> String + where + S: Service, Error = actix_web::Error>, + B: MessageBody, + { + let request = TestRequest::get().uri("/health").to_request(); + let bytes = actix_web::test::call_and_read_body(app, request).await; + String::from_utf8(bytes.to_vec()).unwrap() + } +} + +fn mk_merchant_account(merchant_id: Option) -> Value { + let merchant_id = merchant_id.unwrap_or_else(|| uuid::Uuid::new_v4().to_string()); + + json!({ + "merchant_id": merchant_id, + "merchant_name": "NewAge Retailer", + "merchant_details": { + "primary_contact_person": "John Test", + "primary_email": "JohnTest@test.com", + "primary_phone": "sunt laborum", + "secondary_contact_person": "John Test2", + "secondary_email": "JohnTest2@test.com", + "secondary_phone": "cillum do dolor id", + "website": "www.example.com", + "about_business": "Online Retail with a wide selection of organic products for North America", + "address": { + "line1": "Juspay Router", + "line2": "Koramangala", + "line3": "Stallion", + "city": "Bangalore", + "state": "Karnataka", + "zip": "560095", + "country": "IN" + } + }, + "return_url": "www.example.com/success", + "webhook_details": { + "webhook_version": "1.0.1", + "webhook_username": "ekart_retail", + "webhook_password": "password_ekart@123", + "payment_created_enabled": true, + "payment_succeeded_enabled": true, + "payment_failed_enabled": true + }, + "routing_algorithm": "custom", + "custom_routing_rules": [ + { + "payment_methods_incl": [ + "card", + "card" + ], + "payment_methods_excl": [ + "card", + "card" + ], + "payment_method_types_incl": [ + "credit", + "credit" + ], + "payment_method_types_excl": [ + "credit", + "credit" + ], + "payment_method_issuers_incl": [ + "Citibank", + "JPMorgan" + ], + "payment_method_issuers_excl": [ + "Citibank", + "JPMorgan" + ], + "countries_incl": [ + "US", + "UK", + "IN" + ], + "countries_excl": [ + "US", + "UK", + "IN" + ], + "currencies_incl": [ + "USD", + "EUR" + ], + "currencies_excl": [ + "AED", + "SGD" + ], + "metadata_filters_keys": [ + "payments.udf1", + "payments.udf2" + ], + "metadata_filters_values": [ + "android", + "Category_Electronics" + ], + "connectors_pecking_order": [ + "stripe", + "adyen", + "brain_tree" + ], + "connectors_traffic_weightage_key": [ + "stripe", + "adyen", + "brain_tree" + ], + "connectors_traffic_weightage_value": [ + 50, + 30, + 20 + ] + }, + { + "payment_methods_incl": [ + "card", + "card" + ], + "payment_methods_excl": [ + "card", + "card" + ], + "payment_method_types_incl": [ + "credit", + "credit" + ], + "payment_method_types_excl": [ + "credit", + "credit" + ], + "payment_method_issuers_incl": [ + "Citibank", + "JPMorgan" + ], + "payment_method_issuers_excl": [ + "Citibank", + "JPMorgan" + ], + "countries_incl": [ + "US", + "UK", + "IN" + ], + "countries_excl": [ + "US", + "UK", + "IN" + ], + "currencies_incl": [ + "USD", + "EUR" + ], + "currencies_excl": [ + "AED", + "SGD" + ], + "metadata_filters_keys": [ + "payments.udf1", + "payments.udf2" + ], + "metadata_filters_values": [ + "android", + "Category_Electronics" + ], + "connectors_pecking_order": [ + "stripe", + "adyen", + "brain_tree" + ], + "connectors_traffic_weightage_key": [ + "stripe", + "adyen", + "brain_tree" + ], + "connectors_traffic_weightage_value": [ + 50, + 30, + 20 + ] + } + ], + "sub_merchants_enabled": false, + "metadata": { + "city": "NY", + "unit": "245" + } + }) +} + +fn mk_payment(amount: i32, amount_to_capture: i32) -> Value { + json!({ + "amount": amount, + "currency": "USD", + "confirm": true, + "capture_method": "automatic", + "capture_on": "2022-10-10T10:11:12Z", + "amount_to_capture": amount_to_capture, + "customer_id": "cus_udst2tfldj6upmye2reztkmm4i", + "email": "guest@example.com", + "name": "John Doe", + "phone": "999999999", + "phone_country_code": "+65", + "description": "Its my first payment request", + "authentication_type": "no_three_ds", + "payment_method": "card", + "payment_method_data": { + "card": { + "card_number": "4242424242424242", + "card_exp_month": "10", + "card_exp_year": "35", + "card_holder_name": "John Doe", + "card_cvc": "123" + } + }, + "statement_descriptor_name": "Juspay", + "statement_descriptor_suffix": "Router", + "metadata": { + "udf1": "value1", + "new_customer": "true", + "login_date": "2019-09-10T10:11:12Z" + } + }) +} + +fn mk_connector(connector_name: &str, api_key: &str) -> Value { + json!({ + "connector_type": "fiz_operations", + "connector_name": connector_name, + "connector_account_details": { + "auth_type": "HeaderKey", + "api_key": api_key, + }, + "test_mode": false, + "disabled": false, + "payment_methods_enabled": [ + { + "payment_method": "wallet", + "payment_method_types": [ + "upi_collect", + "upi_intent" + ], + "payment_method_issuers": [ + "labore magna ipsum", + "aute" + ], + "payment_schemes": [ + "Discover", + "Discover" + ], + "accepted_currencies": [ + "AED", + "AED" + ], + "accepted_countries": [ + "in", + "us" + ], + "minimum_amount": 1, + "maximum_amount": 68607706, + "recurring_enabled": true, + "installment_payment_enabled": true + } + ], + "metadata": { + "city": "NY", + "unit": "245" + } + }) +} + +fn _mk_payment_confirm() -> Value { + json!({ + "return_url": "http://example.com/payments", + "setup_future_usage": "on_session", + "authentication_type": "no_three_ds", + "payment_method": "card", + "payment_method_data": { + "card": { + "card_number": "4242424242424242", + "card_exp_month": "10", + "card_exp_year": "35", + "card_holder_name": "John Doe", + "card_cvc": "123" + } + }, + "shipping": {}, + "billing": {} + }) +} + +fn mk_refund(payment_id: &str, amount: usize) -> Value { + let timestamp = common_utils::date_time::now().to_string(); + + json!({ + "payment_id": payment_id, + "refund_id": timestamp.get(23..), + "amount": amount, + "reason": "Customer returned product", + "metadata": { + "udf1": "value1", + "new_customer": "true", + "login_date": "2019-09-10T10:11:12Z" + } + }) +} + +pub struct HNil; + +impl<'de> Deserialize<'de> for HNil { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_any(serde::de::IgnoredAny)?; + Ok(Self) + } +} + +#[derive(Deserialize)] +pub struct HCons { + #[serde(flatten)] + pub head: H, + #[serde(flatten)] + pub tail: T, +} + +#[macro_export] +macro_rules! HList { + () => { $crate::utils::HNil }; + ($head:ty $(, $rest:ty)* $(,)?) => { $crate::utils::HCons<$head, HList![$($rest),*]> }; +} + +#[macro_export] +macro_rules! hlist_pat { + () => { $crate::utils::HNil }; + ($head:pat $(, $rest:pat)* $(,)?) => { $crate::utils::HCons { head: $head, tail: hlist_pat!($($rest),*) } }; +} + +#[derive(Deserialize, Deref)] +pub struct MerchantId { + merchant_id: String, +} + +#[derive(Deserialize, Deref)] +pub struct ApiKey { + api_key: String, +} + +#[derive(Deserialize)] +pub struct Error { + pub message: Message, +} + +#[derive(Deserialize, Deref)] +pub struct Message { + message: String, +} + +#[derive(Deserialize, Deref)] +pub struct PaymentId { + payment_id: String, +} + +#[derive(Deserialize, Deref)] +pub struct Status { + status: String, +} diff --git a/crates/router/tests/webhooks.rs b/crates/router/tests/webhooks.rs index bba7dcb461..f9f0b0c20a 100644 --- a/crates/router/tests/webhooks.rs +++ b/crates/router/tests/webhooks.rs @@ -1,58 +1,58 @@ -use std::sync; +// use std::sync; -use router::{configs::settings, connection, core::webhooks, types::api}; -mod utils; +// use router::{configs::settings, connection, core::webhooks, types::api}; +// mod utils; -fn get_config() -> settings::Settings { - settings::Settings::new().expect("Settings") -} +// fn get_config() -> settings::Settings { +// settings::Settings::new().expect("Settings") +// } -struct TestApp { - redis_conn: connection::RedisPool, -} +// struct TestApp { +// redis_conn: connection::RedisPool, +// } -impl TestApp { - async fn init() -> Self { - utils::setup().await; - let conf = get_config(); +// impl TestApp { +// async fn init() -> Self { +// utils::setup().await; +// let conf = get_config(); - Self { - redis_conn: sync::Arc::new(connection::redis_connection(&conf).await), - } - } -} +// Self { +// redis_conn: sync::Arc::new(connection::redis_connection(&conf.redis).await), +// } +// } +// } -#[actix_web::test] -async fn test_webhook_config_lookup() { - let app = TestApp::init().await; - let timestamp = common_utils::date_time::now(); +// #[actix_web::test] +// async fn test_webhook_config_lookup() { +// let app = TestApp::init().await; +// let timestamp = router::utils::date_time::now(); - let merchant_id = format!("merchant_{timestamp}"); - let connector_id = "stripe"; - let config = serde_json::json!(["payment_intent_success"]); +// let merchant_id = format!("merchant_{timestamp}"); +// let connector_id = "stripe"; +// let config = serde_json::json!(["payment_intent_success"]); - let lookup_res = webhooks::utils::lookup_webhook_event( - connector_id, - &merchant_id, - &api::IncomingWebhookEvent::PaymentIntentSuccess, - sync::Arc::clone(&app.redis_conn), - ) - .await; +// let lookup_res = webhooks::utils::lookup_webhook_event( +// connector_id, +// &merchant_id, +// &api::IncomingWebhookEvent::PaymentIntentSuccess, +// sync::Arc::clone(&app.redis_conn), +// ) +// .await; - assert!(lookup_res); +// assert!(lookup_res); - app.redis_conn - .serialize_and_set_key(&format!("whconf_{merchant_id}_{connector_id}"), &config) - .await - .expect("Save merchant webhook config"); +// app.redis_conn +// .serialize_and_set_key(&format!("whconf_{merchant_id}_{connector_id}"), &config) +// .await +// .expect("Save merchant webhook config"); - let lookup_res = webhooks::utils::lookup_webhook_event( - connector_id, - &merchant_id, - &api::IncomingWebhookEvent::PaymentIntentSuccess, - sync::Arc::clone(&app.redis_conn), - ) - .await; +// let lookup_res = webhooks::utils::lookup_webhook_event( +// connector_id, +// &merchant_id, +// &api::IncomingWebhookEvent::PaymentIntentSuccess, +// sync::Arc::clone(&app.redis_conn), +// ) +// .await; - assert!(lookup_res); -} +// assert!(lookup_res); +// } diff --git a/crates/router_derive/Cargo.toml b/crates/router_derive/Cargo.toml index d94dcf8dce..02265a2ff0 100644 --- a/crates/router_derive/Cargo.toml +++ b/crates/router_derive/Cargo.toml @@ -8,6 +8,7 @@ license = "Apache-2.0" [lib] proc-macro = true +doctest = false [dependencies] proc-macro2 = "1.0.46" diff --git a/crates/router_env/Cargo.toml b/crates/router_env/Cargo.toml index dfe88f6a10..9ee97c25f6 100644 --- a/crates/router_env/Cargo.toml +++ b/crates/router_env/Cargo.toml @@ -22,6 +22,9 @@ serde_urlencoded = "0.7.1" strum = { version = "0.24.1", features = ["derive"] } time = { version = "0.3.14", default-features = false, features = ["formatting"] } tokio = { version = "1.21.2" } + +# We put in a old version, we do not update to avoid clippy errors: https://github.com/tokio-rs/tracing/pull/2270#issuecomment-1282881008 +tracing-attributes = "=0.1.22" tracing = "0.1.36" tracing-actix-web = { version = "0.6.1", features = ["opentelemetry_0_17"], optional = true } tracing-appender = "0.2.2" diff --git a/crates/router_env/src/logger/types.rs b/crates/router_env/src/logger/types.rs index 8c4a20b2ff..bc4673285f 100644 --- a/crates/router_env/src/logger/types.rs +++ b/crates/router_env/src/logger/types.rs @@ -144,7 +144,7 @@ pub enum Category { /// API: general. Api, /// Database: general. - Db, + Store, /// Event: general. Event, /// General: general. diff --git a/crates/router_env/tests/logger.rs b/crates/router_env/tests/logger.rs index e81f07dd63..5e134a8194 100644 --- a/crates/router_env/tests/logger.rs +++ b/crates/router_env/tests/logger.rs @@ -1,8 +1,6 @@ -use std::{path::PathBuf, time::SystemTime}; - use router_env as env; mod test_module; -use env::{workspace_path, TelemetryGuard}; +use env::TelemetryGuard; use test_module::some_module::*; fn logger() -> &'static TelemetryGuard { @@ -29,51 +27,3 @@ async fn basic() -> Result<(), Box> { Ok(()) } - -pub fn last_modified_log() -> Option { - std::fs::read_dir(workspace_path().join("logs")) - .ok()? - .flatten() - .max_by_key(|entry| { - entry - .metadata() - .and_then(|entry| entry.modified()) - .unwrap_or(SystemTime::UNIX_EPOCH) - }) - .map(|n| n.path()) -} - -#[tokio::test] -#[allow(clippy::unwrap_used)] -async fn extra_fields() -> Result<(), Box> { - std::fs::read_dir(workspace_path().join("logs"))?; - - logger(); - - env::log!( - env::Level::WARN, - tag = ?env::Tag::ApiIncomingRequest, - category = ?env::Category::Api, - flow = "some_flow", - session_id = "some_session", - answer = 13, - message2 = "yyy", - message = "Experiment", - ); - - let path = last_modified_log().unwrap(); - let file = std::fs::read_to_string(path).unwrap(); - - file.lines() - .flat_map(serde_json::from_str::>) - .find(|obj| { - obj.get("extra") - == Some(&serde_json::json!({ - "answer": 13, - "message2": "yyy" - })) - }) - .unwrap(); - - Ok(()) -}