From d3929d6b2b4380e9609d64d998197a972f9acc25 Mon Sep 17 00:00:00 2001 From: rupansh Date: Sun, 14 Jul 2024 07:04:11 +0530 Subject: [PATCH 1/8] feat+refactor: initial support for testcontainers --- Cargo.lock | 1076 +++++++++++++++++++++++- Cargo.toml | 21 +- build.rs | 245 ++++-- did/canister_ids.json | 18 +- src/auth/server_impl/store/redis_kv.rs | 2 +- src/canister/generated.rs | 1 + src/canister/mod.rs | 2 - src/consts/local.rs | 7 + src/{consts.rs => consts/mod.rs} | 13 +- src/consts/remote.rs | 7 + src/init/containers.rs | 47 ++ src/init/mod.rs | 159 ++++ src/lib.rs | 2 + src/main.rs | 144 +--- src/state/admin_canisters.rs | 11 +- src/state/canisters.rs | 82 +- 16 files changed, 1583 insertions(+), 254 deletions(-) create mode 100644 src/consts/local.rs rename src/{consts.rs => consts/mod.rs} (85%) create mode 100644 src/consts/remote.rs create mode 100644 src/init/containers.rs create mode 100644 src/init/mod.rs diff --git a/Cargo.lock b/Cargo.lock index bb2bbc37..f762190c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -528,6 +528,67 @@ dependencies = [ "subtle", ] +[[package]] +name = "bollard" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aed08d3adb6ebe0eff737115056652670ae290f177759aac19c30456135f94c" +dependencies = [ + "base64 0.22.1", + "bollard-stubs", + "bytes", + "futures-core", + "futures-util", + "hex", + "home", + "http 1.1.0", + "http-body-util", + "hyper 1.3.1", + "hyper-named-pipe", + "hyper-rustls 0.26.0", + "hyper-util", + "hyperlocal-next", + "log", + "pin-project-lite", + "rustls 0.22.4", + "rustls-native-certs", + "rustls-pemfile 2.1.2", + "rustls-pki-types", + "serde", + "serde_derive", + "serde_json", + "serde_repr", + "serde_urlencoded", + "thiserror", + "tokio", + "tokio-util", + "tower-service", + "url", + "winapi", +] + +[[package]] +name = "bollard-stubs" +version = "1.44.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709d9aa1c37abb89d40f19f5d0ad6f0d88cb1581264e571c9350fc5bb89cf1c5" +dependencies = [ + "serde", + "serde_repr", + "serde_with", +] + +[[package]] +name = "bstr" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -721,6 +782,12 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da987586004ae7c43b7df5e3f7693775068522e1086f8d9b2d74c778a0f43313" +[[package]] +name = "clru" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59" + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -1114,6 +1181,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -1124,6 +1200,18 @@ dependencies = [ "dirs-sys-next", ] +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -1135,6 +1223,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "docker_credential" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31951f49556e34d90ed28342e1df7e1cb7a229c4cab0aecc627b5d91edd41d07" +dependencies = [ + "base64 0.21.7", + "serde", + "serde_json", +] + [[package]] name = "dotenv" version = "0.15.0" @@ -1147,6 +1246,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "669a445ee724c5c69b1b06fe0b63e70a1c84bc9bb7d9696cd4f4e3ec45050408" +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + [[package]] name = "dyn-clone" version = "1.0.17" @@ -1254,6 +1359,18 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum-as-inner" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "enum_dispatch" version = "0.3.13" @@ -1282,6 +1399,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "faster-hex" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" + [[package]] name = "fastrand" version = "2.1.0" @@ -1314,12 +1437,34 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "filetime" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", +] + [[package]] name = "fixedbitset" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "flate2" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1479,6 +1624,512 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "gix" +version = "0.63.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "984c5018adfa7a4536ade67990b3ebc6e11ab57b3d6cd9968de0947ca99b4b06" +dependencies = [ + "gix-actor", + "gix-commitgraph", + "gix-config", + "gix-date", + "gix-diff", + "gix-discover", + "gix-features", + "gix-fs", + "gix-glob", + "gix-hash", + "gix-hashtable", + "gix-index", + "gix-lock", + "gix-macros", + "gix-object", + "gix-odb", + "gix-pack", + "gix-path", + "gix-ref", + "gix-refspec", + "gix-revision", + "gix-revwalk", + "gix-sec", + "gix-tempfile", + "gix-trace", + "gix-traverse", + "gix-url", + "gix-utils", + "gix-validate", + "once_cell", + "parking_lot", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-actor" +version = "0.31.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b8ee65074b2bbb91d9d97c15d172ea75043aefebf9869b5b329149dc76501c" +dependencies = [ + "bstr", + "gix-date", + "gix-utils", + "itoa", + "thiserror", + "winnow 0.6.8", +] + +[[package]] +name = "gix-bitmap" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a371db66cbd4e13f0ed9dc4c0fea712d7276805fccc877f77e96374d317e87ae" +dependencies = [ + "thiserror", +] + +[[package]] +name = "gix-chunk" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45c8751169961ba7640b513c3b24af61aa962c967aaf04116734975cd5af0c52" +dependencies = [ + "thiserror", +] + +[[package]] +name = "gix-commitgraph" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7b102311085da4af18823413b5176d7c500fb2272eaf391cfa8635d8bcb12c4" +dependencies = [ + "bstr", + "gix-chunk", + "gix-features", + "gix-hash", + "memmap2", + "thiserror", +] + +[[package]] +name = "gix-config" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fafe42957e11d98e354a66b6bd70aeea00faf2f62dd11164188224a507c840" +dependencies = [ + "bstr", + "gix-config-value", + "gix-features", + "gix-glob", + "gix-path", + "gix-ref", + "gix-sec", + "memchr", + "once_cell", + "smallvec", + "thiserror", + "unicode-bom", + "winnow 0.6.8", +] + +[[package]] +name = "gix-config-value" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbd06203b1a9b33a78c88252a625031b094d9e1b647260070c25b09910c0a804" +dependencies = [ + "bitflags 2.5.0", + "bstr", + "gix-path", + "libc", + "thiserror", +] + +[[package]] +name = "gix-date" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eed6931f21491ee0aeb922751bd7ec97b4b2fe8fbfedcb678e2a2dce5f3b8c0" +dependencies = [ + "bstr", + "itoa", + "thiserror", + "time", +] + +[[package]] +name = "gix-diff" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b9bd8b2d07b6675a840b56a6c177d322d45fa082672b0dad8f063b25baf0a4" +dependencies = [ + "bstr", + "gix-hash", + "gix-object", + "thiserror", +] + +[[package]] +name = "gix-discover" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc27c699b63da66b50d50c00668bc0b7e90c3a382ef302865e891559935f3dbf" +dependencies = [ + "bstr", + "dunce", + "gix-fs", + "gix-hash", + "gix-path", + "gix-ref", + "gix-sec", + "thiserror", +] + +[[package]] +name = "gix-features" +version = "0.38.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac7045ac9fe5f9c727f38799d002a7ed3583cd777e3322a7c4b43e3cf437dc69" +dependencies = [ + "crc32fast", + "flate2", + "gix-hash", + "gix-trace", + "gix-utils", + "libc", + "once_cell", + "prodash", + "sha1_smol", + "thiserror", + "walkdir", +] + +[[package]] +name = "gix-fs" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3338ff92a2164f5209f185ec0cd316f571a72676bb01d27e22f2867ba69f77a" +dependencies = [ + "fastrand", + "gix-features", + "gix-utils", +] + +[[package]] +name = "gix-glob" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a29ad0990cf02c48a7aac76ed0dbddeb5a0d070034b83675cc3bbf937eace4" +dependencies = [ + "bitflags 2.5.0", + "bstr", + "gix-features", + "gix-path", +] + +[[package]] +name = "gix-hash" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93d7df7366121b5018f947a04d37f034717e113dcf9ccd85c34b58e57a74d5e" +dependencies = [ + "faster-hex", + "thiserror", +] + +[[package]] +name = "gix-hashtable" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ddf80e16f3c19ac06ce415a38b8591993d3f73aede049cb561becb5b3a8e242" +dependencies = [ + "gix-hash", + "hashbrown 0.14.5", + "parking_lot", +] + +[[package]] +name = "gix-index" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d8c5a5f1c58edcbc5692b174cda2703aba82ed17d7176ff4c1752eb48b1b167" +dependencies = [ + "bitflags 2.5.0", + "bstr", + "filetime", + "fnv", + "gix-bitmap", + "gix-features", + "gix-fs", + "gix-hash", + "gix-lock", + "gix-object", + "gix-traverse", + "gix-utils", + "gix-validate", + "hashbrown 0.14.5", + "itoa", + "libc", + "memmap2", + "rustix", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-lock" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bc7fe297f1f4614774989c00ec8b1add59571dc9b024b4c00acb7dedd4e19d" +dependencies = [ + "gix-tempfile", + "gix-utils", + "thiserror", +] + +[[package]] +name = "gix-macros" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "999ce923619f88194171a67fb3e6d613653b8d4d6078b529b15a765da0edcc17" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "gix-object" +version = "0.42.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25da2f46b4e7c2fa7b413ce4dffb87f69eaf89c2057e386491f4c55cadbfe386" +dependencies = [ + "bstr", + "gix-actor", + "gix-date", + "gix-features", + "gix-hash", + "gix-utils", + "gix-validate", + "itoa", + "smallvec", + "thiserror", + "winnow 0.6.8", +] + +[[package]] +name = "gix-odb" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e92b9790e2c919166865d0825b26cc440a387c175bed1b43a2fa99c0e9d45e98" +dependencies = [ + "arc-swap", + "gix-date", + "gix-features", + "gix-fs", + "gix-hash", + "gix-object", + "gix-pack", + "gix-path", + "gix-quote", + "parking_lot", + "tempfile", + "thiserror", +] + +[[package]] +name = "gix-pack" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a8da51212dbff944713edb2141ed7e002eea326b8992070374ce13a6cb610b3" +dependencies = [ + "clru", + "gix-chunk", + "gix-features", + "gix-hash", + "gix-hashtable", + "gix-object", + "gix-path", + "gix-tempfile", + "memmap2", + "parking_lot", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-path" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca987128ffb056d732bd545db5db3d8b103d252fbf083c2567bb0796876619a4" +dependencies = [ + "bstr", + "gix-trace", + "home", + "once_cell", + "thiserror", +] + +[[package]] +name = "gix-quote" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbff4f9b9ea3fa7a25a70ee62f545143abef624ac6aa5884344e70c8b0a1d9ff" +dependencies = [ + "bstr", + "gix-utils", + "thiserror", +] + +[[package]] +name = "gix-ref" +version = "0.44.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3394a2997e5bc6b22ebc1e1a87b41eeefbcfcff3dbfa7c4bd73cb0ac8f1f3e2e" +dependencies = [ + "gix-actor", + "gix-date", + "gix-features", + "gix-fs", + "gix-hash", + "gix-lock", + "gix-object", + "gix-path", + "gix-tempfile", + "gix-utils", + "gix-validate", + "memmap2", + "thiserror", + "winnow 0.6.8", +] + +[[package]] +name = "gix-refspec" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde848865834a54fe4d9b4573f15d0e9a68eaf3d061b42d3ed52b4b8acf880b2" +dependencies = [ + "bstr", + "gix-hash", + "gix-revision", + "gix-validate", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-revision" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e08f8107ed1f93a83bcfbb4c38084c7cb3f6cd849793f1d5eec235f9b13b2b" +dependencies = [ + "bstr", + "gix-date", + "gix-hash", + "gix-hashtable", + "gix-object", + "gix-revwalk", + "gix-trace", + "thiserror", +] + +[[package]] +name = "gix-revwalk" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4181db9cfcd6d1d0fd258e91569dbb61f94cb788b441b5294dd7f1167a3e788f" +dependencies = [ + "gix-commitgraph", + "gix-date", + "gix-hash", + "gix-hashtable", + "gix-object", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-sec" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fddc27984a643b20dd03e97790555804f98cf07404e0e552c0ad8133266a79a1" +dependencies = [ + "bitflags 2.5.0", + "gix-path", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "gix-tempfile" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b0e276cd08eb2a22e9f286a4f13a222a01be2defafa8621367515375644b99" +dependencies = [ + "gix-fs", + "libc", + "once_cell", + "parking_lot", + "tempfile", +] + +[[package]] +name = "gix-trace" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f924267408915fddcd558e3f37295cc7d6a3e50f8bd8b606cee0808c3915157e" + +[[package]] +name = "gix-traverse" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f20cb69b63eb3e4827939f42c05b7756e3488ef49c25c412a876691d568ee2a0" +dependencies = [ + "bitflags 2.5.0", + "gix-commitgraph", + "gix-date", + "gix-hash", + "gix-hashtable", + "gix-object", + "gix-revwalk", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-url" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0db829ebdca6180fbe32be7aed393591df6db4a72dbbc0b8369162390954d1cf" +dependencies = [ + "bstr", + "gix-features", + "gix-path", + "home", + "thiserror", + "url", +] + +[[package]] +name = "gix-utils" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35192df7fd0fa112263bad8021e2df7167df4cc2a6e6d15892e1e55621d3d4dc" +dependencies = [ + "fastrand", + "unicode-normalization", +] + +[[package]] +name = "gix-validate" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82c27dd34a49b1addf193c92070bcbf3beaf6e10f16a78544de6372e146a0acf" +dependencies = [ + "bstr", + "thiserror", +] + [[package]] name = "gloo" version = "0.11.0" @@ -1669,7 +2320,7 @@ version = "0.1.0" source = "git+https://github.com/go-bazzinga/gob-cloudflare?rev=c847ba87ecc73a33520b24bd62503420d7e23e3e#c847ba87ecc73a33520b24bd62503420d7e23e3e" dependencies = [ "bytes", - "reqwest 0.12.4", + "reqwest 0.12.5", "serde", "serde_json", "thiserror", @@ -1798,6 +2449,51 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hickory-proto" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07698b8420e2f0d6447a436ba999ec85d8fbf2a398bbd737b82cac4a2e96e512" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.4.0", + "ipnet", + "once_cell", + "rand", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28757f23aa75c98f254cf0405e6d8c25b831b32921b050a66692427679b1f243" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot", + "rand", + "resolv-conf", + "smallvec", + "thiserror", + "tokio", + "tracing", +] + [[package]] name = "hkdf" version = "0.12.4" @@ -1811,15 +2507,36 @@ dependencies = [ name = "hmac" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" dependencies = [ - "digest 0.10.7", + "libc", + "match_cfg", + "winapi", ] [[package]] name = "hot-or-not-web-leptos-ssr" version = "0.1.0" dependencies = [ + "anyhow", "axum 0.7.5", "axum-extra", "bb8", @@ -1857,12 +2574,13 @@ dependencies = [ "rand_chacha", "redb", "redis", - "reqwest 0.12.4", + "reqwest 0.12.5", "serde", "serde-wasm-bindgen", "serde_bytes", "serde_json", "simple_logger", + "testcontainers", "thiserror", "tokio", "tonic", @@ -1876,6 +2594,7 @@ dependencies = [ "web-time", "yral-metadata-client", "yral-metadata-types", + "yral-testcontainers", ] [[package]] @@ -2006,6 +2725,21 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-named-pipe" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278" +dependencies = [ + "hex", + "hyper 1.3.1", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", + "winapi", +] + [[package]] name = "hyper-rustls" version = "0.24.2" @@ -2030,13 +2764,34 @@ dependencies = [ "http 1.1.0", "hyper 1.3.1", "hyper-util", + "log", "rustls 0.22.4", + "rustls-native-certs", "rustls-pki-types", "tokio", "tokio-rustls 0.25.0", "tower-service", ] +[[package]] +name = "hyper-rustls" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.3.1", + "hyper-util", + "rustls 0.23.10", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.0", + "tower-service", + "webpki-roots 0.26.1", +] + [[package]] name = "hyper-timeout" version = "0.4.1" @@ -2085,6 +2840,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "hyperlocal-next" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acf569d43fa9848e510358c07b80f4adf34084ddc28c6a4a651ee8474c070dcc" +dependencies = [ + "hex", + "http-body-util", + "hyper 1.3.1", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -2409,6 +3179,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "idna" version = "0.5.0" @@ -2474,6 +3254,18 @@ version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767" +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2", + "widestring", + "windows-sys 0.48.0", + "winreg 0.50.0", +] + [[package]] name = "ipnet" version = "2.9.0" @@ -2887,6 +3679,12 @@ dependencies = [ "serde_test", ] +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -2950,6 +3748,15 @@ dependencies = [ "hashbrown 0.14.5", ] +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "manyhow" version = "0.10.4" @@ -2973,6 +3780,12 @@ dependencies = [ "quote", ] +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + [[package]] name = "matchit" version = "0.7.3" @@ -2985,6 +3798,15 @@ version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +[[package]] +name = "memmap2" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" +dependencies = [ + "libc", +] + [[package]] name = "mime" version = "0.3.17" @@ -3283,6 +4105,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "ordered-float" version = "2.10.1" @@ -3349,11 +4177,36 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.1", "smallvec", "windows-targets 0.52.5", ] +[[package]] +name = "parse-display" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914a1c2265c98e2446911282c6ac86d8524f495792c38c5bd884f80499c7538a" +dependencies = [ + "parse-display-derive", + "regex", + "regex-syntax 0.8.3", +] + +[[package]] +name = "parse-display-derive" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ae7800a4c974efd12df917266338e79a7a74415173caf7e70aa0a0707345281" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "regex-syntax 0.8.3", + "structmeta", + "syn 2.0.66", +] + [[package]] name = "paste" version = "1.0.15" @@ -3618,6 +4471,12 @@ dependencies = [ "yansi", ] +[[package]] +name = "prodash" +version = "28.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744a264d26b88a6a7e37cbad97953fa233b94d585236310bcbc88474b4092d79" + [[package]] name = "prost" version = "0.12.6" @@ -3680,6 +4539,59 @@ dependencies = [ "cc", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls 0.23.10", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring", + "rustc-hash", + "rustls 0.23.10", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -3786,6 +4698,15 @@ dependencies = [ "url", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_syscall" version = "0.5.1" @@ -3886,20 +4807,22 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ "base64 0.22.1", "bytes", + "encoding_rs", "futures-core", "futures-util", "h2 0.4.5", + "hickory-resolver", "http 1.1.0", "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-rustls 0.26.0", + "hyper-rustls 0.27.2", "hyper-tls", "hyper-util", "ipnet", @@ -3911,16 +4834,18 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.22.4", + "quinn", + "rustls 0.23.10", + "rustls-native-certs", "rustls-pemfile 2.1.2", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "tokio", "tokio-native-tls", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.0", "tower-service", "url", "wasm-bindgen", @@ -3930,6 +4855,16 @@ dependencies = [ "winreg 0.52.0", ] +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + [[package]] name = "rfc6979" version = "0.4.0" @@ -4049,6 +4984,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls" +version = "0.23.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.4", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.7.0" @@ -4454,6 +5403,12 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + [[package]] name = "sha2" version = "0.9.9" @@ -4478,6 +5433,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "signature" version = "2.2.0" @@ -4613,6 +5577,29 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "structmeta" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e1575d8d40908d70f6fd05537266b90ae71b15dbbe7a8b7dffa2b759306d329" +dependencies = [ + "proc-macro2", + "quote", + "structmeta-derive", + "syn 2.0.66", +] + +[[package]] +name = "structmeta-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "subtle" version = "2.5.0" @@ -4724,6 +5711,35 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "testcontainers" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb74bff469141dfded423ce9b8aa47430bfd9058e8d8ddac4a7c0966da0025bb" +dependencies = [ + "async-trait", + "bollard", + "bollard-stubs", + "bytes", + "dirs", + "docker_credential", + "either", + "futures", + "log", + "memchr", + "parse-display", + "pin-project-lite", + "reqwest 0.12.5", + "serde", + "serde_json", + "serde_with", + "thiserror", + "tokio", + "tokio-stream", + "tokio-util", + "url", +] + [[package]] name = "thiserror" version = "1.0.61" @@ -4815,6 +5831,7 @@ dependencies = [ "num_cpus", "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.48.0", @@ -4883,6 +5900,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls 0.23.10", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.15" @@ -5140,6 +6168,12 @@ version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +[[package]] +name = "unicode-bom" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217" + [[package]] name = "unicode-ident" version = "1.0.12" @@ -5196,7 +6230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna", + "idna 0.5.0", "percent-encoding", "serde", ] @@ -5373,6 +6407,12 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" + [[package]] name = "winapi" version = "0.3.9" @@ -5620,7 +6660,7 @@ version = "0.1.0" source = "git+https://github.com/go-bazzinga/yral-metadata?rev=c2c5d254ac273681a66966d62b6f01785679a1be#c2c5d254ac273681a66966d62b6f01785679a1be" dependencies = [ "ic-agent", - "reqwest 0.12.4", + "reqwest 0.12.5", "thiserror", "yral-identity", "yral-metadata-types", @@ -5637,6 +6677,16 @@ dependencies = [ "yral-identity", ] +[[package]] +name = "yral-testcontainers" +version = "0.1.0" +source = "git+https://github.com/go-bazzinga/yral-testcontainers?rev=14740097702fbc925ec2dbaa2b4a7660775576f4#14740097702fbc925ec2dbaa2b4a7660775576f4" +dependencies = [ + "anyhow", + "gix", + "testcontainers", +] + [[package]] name = "zerocopy" version = "0.7.34" diff --git a/Cargo.toml b/Cargo.toml index da1c1776..51816e06 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ leptos_meta = { version = "0.6", features = ["nightly"] } leptos_router = { version = "0.6", features = ["nightly"] } log = "0.4" simple_logger = "4.0" -tokio = { version = "1", optional = true, features = ["rt-multi-thread"] } +tokio = { version = "1", optional = true, features = ["rt-multi-thread", "signal"] } tower = { version = "0.4", optional = true } tower-http = { version = "0.5", features = ["fs"], optional = true } wasm-bindgen = "=0.2.92" @@ -84,7 +84,6 @@ bb8-redis = { version = "0.15.0", optional = true } gob-cloudflare = { git = "https://github.com/go-bazzinga/gob-cloudflare", rev = "c847ba87ecc73a33520b24bd62503420d7e23e3e", default-features = false, optional = true } yral-metadata-client = { git = "https://github.com/go-bazzinga/yral-metadata", rev = "c2c5d254ac273681a66966d62b6f01785679a1be", default-features = false } yral-metadata-types = { git = "https://github.com/go-bazzinga/yral-metadata", rev = "c2c5d254ac273681a66966d62b6f01785679a1be", default-features = false } - gloo-utils = { version = "0.2.0", features = ["serde"] } tonic = { version = "0.11.0", features = [ "tls", @@ -92,6 +91,8 @@ tonic = { version = "0.11.0", features = [ ], optional = true } prost = { version = "0.12.4", optional = true } hmac = { version = "0.12.1", optional = true } +testcontainers = { version = "0.20.0", optional = true } +yral-testcontainers = { git = "https://github.com/go-bazzinga/yral-testcontainers", rev = "14740097702fbc925ec2dbaa2b4a7660775576f4", optional = true } [build-dependencies] serde = { version = "1.0", features = ["derive"] } @@ -99,6 +100,7 @@ candid_parser = "0.1.1" serde_json = "1.0.110" convert_case = "0.6.0" tonic-build = "0.11.0" +anyhow = "1.0.86" [features] hydrate = [ @@ -147,6 +149,7 @@ redis-kv = [] cloudflare = ["dep:gob-cloudflare"] backend-admin = [] ga4 = [] +mock-wallet-history = ["dep:rand_chacha"] release-bin = [ "ssr", "cloudflare", @@ -164,8 +167,18 @@ release-lib = [ "oauth-hydrate", "ga4", ] - -mock-wallet-history = ["dep:rand_chacha"] +local-bin = [ + "ssr", + "redis-kv", + "local-auth", + "dep:testcontainers", + "dep:yral-testcontainers", +] +local-lib = [ + "hydrate", + "redis-kv", + "local-auth", +] [profile.wasm-release] inherits = "release" diff --git a/build.rs b/build.rs index e9dcba72..695a37d3 100644 --- a/build.rs +++ b/build.rs @@ -1,106 +1,181 @@ -use std::{collections::HashMap, env, ffi::OsStr, fs, io, path::PathBuf}; +use anyhow::Result; -use candid_parser::Principal; -use convert_case::{Case, Casing}; -use serde::Deserialize; +mod build_common { + use std::{collections::HashMap, env, ffi::OsStr, fs, io, path::PathBuf}; -#[derive(Deserialize)] -struct CanId { - ic: Principal, -} + use anyhow::Result; + use candid_parser::Principal; + use convert_case::{Case, Casing}; + use serde::Deserialize; -fn read_candid_ids() -> io::Result> { - let can_ids_file = fs::File::open("did/canister_ids.json")?; - let reader = io::BufReader::new(can_ids_file); - Ok(serde_json::from_reader(reader).expect("invalid candid ids")) -} + #[derive(Deserialize)] + struct CanId { + ic: Principal, + local: Principal, + } + + fn read_candid_ids() -> Result> { + let can_ids_file = fs::File::open("did/canister_ids.json")?; + let reader = io::BufReader::new(can_ids_file); + Ok(serde_json::from_reader(reader)?) + } + + fn generate_canister_id_mod(can_ids: Vec<(String, Principal)>) -> String { + let mut canister_id_mod = String::new(); + for (canister, can_id) in can_ids { + let can_upper = canister.to_case(Case::UpperSnake); + // CANISTER_NAME_ID: Principal = Principal::from_slice(&[..]); + canister_id_mod.push_str(&format!( + "pub const {can_upper}_ID: candid::Principal = candid::Principal::from_slice(&{:?});\n", + can_id.as_slice() + )); + } + canister_id_mod + } -fn build_gprc_client() -> Result<(), Box> { - let proto_file = "contracts/projects/warehouse_events/warehouse_events.proto"; - let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + fn build_canister_ids(out_dir: &str) -> Result<()> { + let can_ids = read_candid_ids()?; + let mut local_can_ids = Vec::<(String, Principal)>::new(); + let mut ic_can_ids = Vec::<(String, Principal)>::new(); + for (canister, can_id) in can_ids { + local_can_ids.push((canister.clone(), can_id.local)); + ic_can_ids.push((canister, can_id.ic)); + } - tonic_build::configure() - .build_client(true) - .build_server(false) - .out_dir(out_dir) - .compile(&[proto_file], &["proto"])?; + let local_canister_id_mod = generate_canister_id_mod(local_can_ids); + let ic_canister_id_mod = generate_canister_id_mod(ic_can_ids); + + let canister_id_mod_contents = format!( + r#" + #[cfg(any(feature = "local-bin", feature = "local-lib"))] + mod local {{ + {local_canister_id_mod} + }} + + #[cfg(not(any(feature = "local-bin", feature = "local-lib")))] + mod ic {{ + {ic_canister_id_mod} + }} + #[cfg(any(feature = "local-bin", feature = "local-lib"))] + pub use local::*; + #[cfg(not(any(feature = "local-bin", feature = "local-lib")))] + pub use ic::*; +"# + ); + let canister_id_mod_path = PathBuf::from(out_dir).join("canister_ids.rs"); + fs::write(canister_id_mod_path, canister_id_mod_contents)?; - let proto_file = "contracts/projects/off_chain/off_chain.proto"; - let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + Ok(()) + } - tonic_build::configure() - .build_client(true) - .build_server(false) - .out_dir(out_dir) - .compile(&[proto_file], &["proto"])?; + fn build_did_intf() -> Result<()> { + println!("cargo:rerun-if-changed=did/*"); + + let mut candid_config = candid_parser::bindings::rust::Config::new(); + candid_config.set_target(candid_parser::bindings::rust::Target::Agent); + let mut did_mod_contents = String::new(); + + // create $OUT_DIR/did + let out_dir = env::var("OUT_DIR").unwrap(); + let did_dir = PathBuf::from(&out_dir).join("did"); + fs::create_dir_all(&did_dir)?; + + // Auto generate bindings for did files + for didinfo in fs::read_dir("did")? { + let didpath = didinfo?.path(); + if didpath.extension() != Some(OsStr::new("did")) { + continue; + } + let file_name = didpath.file_stem().unwrap().to_str().unwrap(); + + // compile bindings from did + let service_name: String = file_name.to_case(Case::Pascal); + candid_config.set_service_name(service_name); + let (type_env, actor) = + candid_parser::pretty_check_file(&didpath).unwrap_or_else(|e| { + panic!( + "invalid did file: {}, err: {e}", + didpath.as_os_str().to_string_lossy() + ) + }); + let bindings = + candid_parser::bindings::rust::compile(&candid_config, &type_env, &actor); + + // write bindings to $OUT_DIR/did/.rs + let mut binding_file = did_dir.clone(); + binding_file.push(file_name); + binding_file.set_extension("rs"); + fs::write(&binding_file, bindings)?; + + // #[path = "$OUT_DIR/did/.rs"] pub mod ; + did_mod_contents.push_str(&format!( + "#[path = \"{}\"] pub mod {};\n", + binding_file.to_string_lossy(), + file_name + )); + } - Ok(()) + // create mod file for did bindings + // ideally i'd like to manually write this file in src/canister/mod.rs + // but can't, due to https://github.com/rust-lang/rfcs/issues/752 + let binding_mod_file = PathBuf::from(&out_dir).join("did").join("mod.rs"); + fs::write(binding_mod_file, did_mod_contents)?; + + build_canister_ids(&out_dir)?; + + Ok(()) + } + + pub fn build_common() -> Result<()> { + build_did_intf()?; + Ok(()) + } } -fn main() -> io::Result<()> { - println!("cargo:rerun-if-changed=did/*"); +#[cfg(feature = "ssr")] +mod build_ssr { + use std::{env, path::PathBuf}; - let can_ids = read_candid_ids()?; + use anyhow::Result; - let mut candid_config = candid_parser::bindings::rust::Config::new(); - candid_config.set_target(candid_parser::bindings::rust::Target::Agent); - let mut did_mod_contents = String::new(); + fn build_gprc_client() -> Result<()> { + println!("cargo:rerun-if-changed=contracts/projects/*"); - // create $OUT_DIR/did - let out_dir = env::var("OUT_DIR").unwrap(); - let did_dir = PathBuf::from(&out_dir).join("did"); - fs::create_dir_all(&did_dir)?; + let proto_file = "contracts/projects/warehouse_events/warehouse_events.proto"; + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); - // Auto generate bindings for did files - for didinfo in fs::read_dir("did")? { - let didpath = didinfo?.path(); - if didpath.extension() != Some(OsStr::new("did")) { - continue; - } - let file_name = didpath.file_stem().unwrap().to_str().unwrap(); - - // compile bindings from did - candid_config.set_canister_id( - can_ids - .get(file_name) - .unwrap_or_else(|| panic!("no canister id for {file_name}")) - .ic, - ); - let service_name: String = file_name.to_case(Case::Pascal); - candid_config.set_service_name(service_name); - let (type_env, actor) = candid_parser::pretty_check_file(&didpath).unwrap_or_else(|e| { - panic!( - "invalid did file: {}, err: {e}", - didpath.as_os_str().to_string_lossy() - ) - }); - let bindings = candid_parser::bindings::rust::compile(&candid_config, &type_env, &actor); - - // write bindings to $OUT_DIR/did/.rs - let mut binding_file = did_dir.clone(); - binding_file.push(file_name); - binding_file.set_extension("rs"); - fs::write(&binding_file, bindings)?; - - // #[path = "$OUT_DIR/did/.rs"] pub mod ; - did_mod_contents.push_str(&format!( - "#[path = \"{}\"] pub mod {};\n", - binding_file.to_string_lossy(), - file_name - )); + tonic_build::configure() + .build_client(true) + .build_server(false) + .out_dir(out_dir) + .compile(&[proto_file], &["proto"])?; + + let proto_file = "contracts/projects/off_chain/off_chain.proto"; + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + + tonic_build::configure() + .build_client(true) + .build_server(false) + .out_dir(out_dir) + .compile(&[proto_file], &["proto"])?; + + Ok(()) } - // create mod file for did bindings - // ideally i'd like to manually write this file in src/canister/mod.rs - // but can't, due to https://github.com/rust-lang/rfcs/issues/752 - let binding_mod_file = PathBuf::from(&out_dir).join("did").join("mod.rs"); - fs::write(binding_mod_file, did_mod_contents)?; + pub fn build_ssr() -> Result<()> { + build_gprc_client()?; + + Ok(()) + } +} - // Build GRPC client - match build_gprc_client() { - Ok(_) => (), - Err(e) => panic!("Failed to build GRPC client: {e}"), +fn main() -> Result<()> { + #[cfg(feature = "ssr")] + { + build_ssr::build_ssr()?; } + build_common::build_common()?; + Ok(()) } diff --git a/did/canister_ids.json b/did/canister_ids.json index e35b0018..bc34e721 100644 --- a/did/canister_ids.json +++ b/did/canister_ids.json @@ -1,20 +1,26 @@ { "configuration": { - "ic": "efsfj-sqaaa-aaaap-qatwa-cai" + "ic": "efsfj-sqaaa-aaaap-qatwa-cai", + "local": "bnz7o-iuaaa-aaaaa-qaaaa-cai" }, "data_backup": { - "ic": "jwktp-qyaaa-aaaag-abcfa-cai" + "ic": "jwktp-qyaaa-aaaag-abcfa-cai", + "local": "bkyz2-fmaaa-aaaaa-qaaaq-cai" }, "individual_user_template": { - "ic": "dc47w-kaaaa-aaaak-qav3q-cai" + "ic": "dc47w-kaaaa-aaaak-qav3q-cai", + "local": "bd3sg-teaaa-aaaaa-qaaba-cai" }, "platform_orchestrator": { - "ic": "74zq4-iqaaa-aaaam-ab53a-cai" + "ic": "74zq4-iqaaa-aaaam-ab53a-cai", + "local": "bw4dl-smaaa-aaaaa-qaacq-cai" }, "post_cache": { - "ic": "zyajx-3yaaa-aaaag-acoga-cai" + "ic": "zyajx-3yaaa-aaaag-acoga-cai", + "local": "be2us-64aaa-aaaaa-qaabq-cai" }, "user_index": { - "ic": "rimrc-piaaa-aaaao-aaljq-cai" + "ic": "rimrc-piaaa-aaaao-aaljq-cai", + "local": "br5f7-7uaaa-aaaaa-qaaca-cai" } } \ No newline at end of file diff --git a/src/auth/server_impl/store/redis_kv.rs b/src/auth/server_impl/store/redis_kv.rs index d7e6970d..aef3f6d4 100644 --- a/src/auth/server_impl/store/redis_kv.rs +++ b/src/auth/server_impl/store/redis_kv.rs @@ -24,7 +24,7 @@ impl KVStore for RedisKV { async fn write(&self, key: String, value: String) -> Result<(), KVError> { let mut con = self.0.get().await?; - con.hset(key, AUTH_FIELD, value).await?; + let _replaced: bool = con.hset(key, AUTH_FIELD, value).await?; Ok(()) } } diff --git a/src/canister/generated.rs b/src/canister/generated.rs index 5614f263..2f10c298 100644 --- a/src/canister/generated.rs +++ b/src/canister/generated.rs @@ -1 +1,2 @@ include!(concat!(env!("OUT_DIR"), "/did/mod.rs")); +include!(concat!(env!("OUT_DIR"), "/canister_ids.rs")); diff --git a/src/canister/mod.rs b/src/canister/mod.rs index 69cfb6ae..5e1fac5f 100644 --- a/src/canister/mod.rs +++ b/src/canister/mod.rs @@ -4,5 +4,3 @@ mod generated; pub mod utils; pub use generated::*; - -pub const AGENT_URL: &str = "https://ic0.app"; diff --git a/src/consts/local.rs b/src/consts/local.rs new file mode 100644 index 00000000..66f17f8f --- /dev/null +++ b/src/consts/local.rs @@ -0,0 +1,7 @@ +use once_cell::sync::Lazy; +use reqwest::Url; + +pub static METADATA_API_BASE: Lazy = + Lazy::new(|| Url::parse("http://localhost:8001").unwrap()); + +pub const AGENT_URL: &str = "http://localhost:4943"; diff --git a/src/consts.rs b/src/consts/mod.rs similarity index 85% rename from src/consts.rs rename to src/consts/mod.rs index 8e045825..21cb6dd3 100644 --- a/src/consts.rs +++ b/src/consts/mod.rs @@ -1,3 +1,13 @@ +#[cfg(any(feature = "local-bin", feature = "local-lib"))] +mod local; +#[cfg(any(feature = "local-bin", feature = "local-lib"))] +pub use local::*; + +#[cfg(not(any(feature = "local-bin", feature = "local-lib")))] +mod remote; +#[cfg(not(any(feature = "local-bin", feature = "local-lib")))] +pub use remote::*; + use once_cell::sync::Lazy; use reqwest::Url; @@ -9,8 +19,7 @@ pub static CF_BASE_URL: Lazy = Lazy::new(|| Url::parse("https://api.cloudflare.com/client/v4/").unwrap()); pub const NSFW_TOGGLE_STORE: &str = "nsfw-enabled"; pub const REFERRER_STORE: &str = "referrer"; -pub static METADATA_API_BASE: Lazy = - Lazy::new(|| Url::parse("https://yral-metadata.fly.dev").unwrap()); + pub static OFF_CHAIN_AGENT_GRPC_URL: Lazy = Lazy::new(|| Url::parse("https://icp-off-chain-agent.fly.dev:443").unwrap()); // G-6W5Q2MRX0E to test locally | G-PLNNETMSLM diff --git a/src/consts/remote.rs b/src/consts/remote.rs new file mode 100644 index 00000000..2296c4b8 --- /dev/null +++ b/src/consts/remote.rs @@ -0,0 +1,7 @@ +use once_cell::sync::Lazy; +use reqwest::Url; + +pub static METADATA_API_BASE: Lazy = + Lazy::new(|| Url::parse("https://yral-metadata.fly.dev").unwrap()); + +pub const AGENT_URL: &str = "https://ic0.app"; diff --git a/src/init/containers.rs b/src/init/containers.rs new file mode 100644 index 00000000..2f39ca21 --- /dev/null +++ b/src/init/containers.rs @@ -0,0 +1,47 @@ +use testcontainers::{ + core::{ContainerPort, IntoContainerPort, WaitFor}, + runners::AsyncRunner, + ContainerAsync, GenericImage, Image, ImageExt, +}; +use yral_testcontainers::{ + backend::{self, YralBackend}, + metadata::{self, YralMetadata}, +}; + +type MaybeContainer = Option>; + +/// Holds all the containers that are started for local testing +/// we are required to hold these as ContainerAsync stops the container +/// on drop +#[derive(Default)] +pub struct TestContainers { + redis: MaybeContainer, + metadata: MaybeContainer, + backend: MaybeContainer, +} + +impl TestContainers { + async fn start_image(image: I, port: impl Into) -> ContainerAsync { + let port = port.into(); + image + .with_mapped_port(port.as_u16(), port) + .start() + .await + .map_err(|e| format!("Failed to start container: {}", e)) + .unwrap() + } + pub async fn start_redis(&mut self) { + let redis_im = GenericImage::new("redis", "7.2.4") + .with_exposed_port(6379.tcp()) + .with_wait_for(WaitFor::message_on_stdout("Ready to accept connections")); + self.redis = Some(Self::start_image(redis_im, 6379.tcp()).await); + } + + pub async fn start_metadata(&mut self) { + self.metadata = Some(Self::start_image(YralMetadata, metadata::REST_PORT).await); + } + + pub async fn start_backend(&mut self) { + self.backend = Some(Self::start_image(YralBackend, backend::AGENT_PORT).await); + } +} diff --git a/src/init/mod.rs b/src/init/mod.rs new file mode 100644 index 00000000..f6e75dc8 --- /dev/null +++ b/src/init/mod.rs @@ -0,0 +1,159 @@ +#[cfg(feature = "local-bin")] +pub mod containers; + +use std::env; + +use axum_extra::extract::cookie::Key; +use leptos::LeptosOptions; +use leptos_router::RouteListing; + +use crate::{ + auth::server_impl::store::KVStoreImpl, + state::{canisters::Canisters, server::AppState}, +}; + +#[cfg(feature = "cloudflare")] +fn init_cf() -> gob_cloudflare::CloudflareAuth { + use gob_cloudflare::{CloudflareAuth, Credentials}; + let creds = Credentials { + token: env::var("CF_TOKEN").expect("`CF_TOKEN` is required!"), + account_id: env::var("CF_ACCOUNT_ID").expect("`CF_ACCOUNT_ID` is required!"), + }; + CloudflareAuth::new(creds) +} + +fn init_cookie_key() -> Key { + let cookie_key_str = env::var("COOKIE_KEY").expect("`COOKIE_KEY` is required!"); + let cookie_key_raw = + hex::decode(cookie_key_str).expect("Invalid `COOKIE_KEY` (must be length 128 hex)"); + Key::from(&cookie_key_raw) +} + +#[cfg(feature = "oauth-ssr")] +fn init_google_oauth() -> openidconnect::core::CoreClient { + use crate::consts::google::{GOOGLE_AUTH_URL, GOOGLE_ISSUER_URL, GOOGLE_TOKEN_URL}; + use openidconnect::{ + core::CoreClient, AuthUrl, ClientId, ClientSecret, IssuerUrl, RedirectUrl, TokenUrl, + }; + + let client_id = env::var("GOOGLE_CLIENT_ID").expect("`GOOGLE_CLIENT_ID` is required!"); + let client_secret = + env::var("GOOGLE_CLIENT_SECRET").expect("`GOOGLE_CLIENT_SECRET` is required!"); + let redirect_uri = env::var("GOOGLE_REDIRECT_URL").expect("`GOOGLE_REDIRECT_URL` is required!"); + + CoreClient::new( + ClientId::new(client_id), + Some(ClientSecret::new(client_secret)), + IssuerUrl::new(GOOGLE_ISSUER_URL.to_string()).unwrap(), + AuthUrl::new(GOOGLE_AUTH_URL.to_string()).unwrap(), + Some(TokenUrl::new(GOOGLE_TOKEN_URL.to_string()).unwrap()), + None, + // We don't validate id_tokens against Google's public keys + Default::default(), + ) + .set_redirect_uri(RedirectUrl::new(redirect_uri).unwrap()) +} + +#[cfg(feature = "ga4")] +async fn init_grpc_offchain_channel() -> tonic::transport::Channel { + use crate::consts::OFF_CHAIN_AGENT_GRPC_URL; + use tonic::transport::Channel; + + let off_chain_agent_url = OFF_CHAIN_AGENT_GRPC_URL.as_ref(); + Channel::from_static(off_chain_agent_url) + .connect() + .await + .expect("Couldn't connect to off-chain agent") +} + +#[cfg(feature = "backend-admin")] +fn init_admin_canisters() -> crate::state::admin_canisters::AdminCanisters { + use crate::state::admin_canisters::AdminCanisters; + use ic_agent::identity::BasicIdentity; + + let admin_id_pem = + env::var("BACKEND_ADMIN_IDENTITY").expect("`BACKEND_ADMIN_IDENTITY` is required!"); + let admin_id_pem_by = admin_id_pem.as_bytes(); + let admin_id = + BasicIdentity::from_pem(admin_id_pem_by).expect("Invalid `BACKEND_ADMIN_IDENTITY`"); + AdminCanisters::new(admin_id) +} + +pub struct AppStateRes { + pub app_state: AppState, + #[cfg(feature = "local-bin")] + pub containers: containers::TestContainers, +} + +pub struct AppStateBuilder { + leptos_options: LeptosOptions, + routes: Vec, + #[cfg(feature = "local-bin")] + containers: containers::TestContainers, +} + +impl AppStateBuilder { + pub fn new(leptos_options: LeptosOptions, routes: Vec) -> Self { + Self { + leptos_options, + routes, + #[cfg(feature = "local-bin")] + containers: containers::TestContainers::default(), + } + } + + async fn init_kv(&mut self) -> KVStoreImpl { + #[cfg(feature = "redis-kv")] + { + use crate::auth::server_impl::store::redis_kv::RedisKV; + let redis_url: String; + #[cfg(feature = "local-bin")] + { + self.containers.start_redis().await; + redis_url = "redis://127.0.0.1:6379".to_string(); + } + #[cfg(not(feature = "local-bin"))] + { + redis_url = env::var("REDIS_URL").expect("`REDIS_URL` is required!"); + } + KVStoreImpl::Redis(RedisKV::new(&redis_url).await.unwrap()) + } + + #[cfg(not(feature = "redis-kv"))] + { + use crate::auth::server_impl::store::redb_kv::ReDBKV; + KVStoreImpl::ReDB(ReDBKV::new().expect("Failed to initialize ReDB")) + } + } + + pub async fn build(mut self) -> AppStateRes { + let kv = self.init_kv().await; + #[cfg(feature = "local-bin")] + { + self.containers.start_backend().await; + self.containers.start_metadata().await; + } + + let app_state = AppState { + leptos_options: self.leptos_options, + canisters: Canisters::default(), + routes: self.routes, + #[cfg(feature = "backend-admin")] + admin_canisters: init_admin_canisters(), + #[cfg(feature = "cloudflare")] + cloudflare: init_cf(), + kv, + cookie_key: init_cookie_key(), + #[cfg(feature = "oauth-ssr")] + google_oauth: init_google_oauth(), + #[cfg(feature = "ga4")] + grpc_offchain_channel: init_grpc_offchain_channel().await, + }; + + AppStateRes { + app_state, + #[cfg(feature = "local-bin")] + containers: self.containers, + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 7b3f9bab..7d54b800 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,8 @@ pub mod consts; pub mod error_template; #[cfg(feature = "ssr")] pub mod fallback; +#[cfg(feature = "ssr")] +pub mod init; pub mod js; pub mod page; pub mod state; diff --git a/src/main.rs b/src/main.rs index 318c4885..abb535a6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,3 @@ -use std::env; - use axum::{ body::Body as AxumBody, extract::{Path, State}, @@ -7,12 +5,8 @@ use axum::{ response::{IntoResponse, Response}, }; use axum::{routing::get, Router}; -use axum_extra::extract::cookie::Key; -use hot_or_not_web_leptos_ssr::{app::App, state::server::AppState}; -use hot_or_not_web_leptos_ssr::{ - auth::server_impl::store::KVStoreImpl, fallback::file_and_error_handler, -}; -use hot_or_not_web_leptos_ssr::{consts::OFF_CHAIN_AGENT_GRPC_URL, state::canisters::Canisters}; +use hot_or_not_web_leptos_ssr::fallback::file_and_error_handler; +use hot_or_not_web_leptos_ssr::{app::App, init::AppStateBuilder, state::server::AppState}; use leptos::{get_configuration, logging::log, provide_context}; use leptos_axum::handle_server_fns_with_context; use leptos_axum::{generate_route_list, LeptosRoutes}; @@ -68,89 +62,6 @@ pub async fn leptos_routes_handler( handler(req).await.into_response() } -#[cfg(feature = "cloudflare")] -fn init_cf() -> gob_cloudflare::CloudflareAuth { - use gob_cloudflare::{CloudflareAuth, Credentials}; - let creds = Credentials { - token: env::var("CF_TOKEN").expect("`CF_TOKEN` is required!"), - account_id: env::var("CF_ACCOUNT_ID").expect("`CF_ACCOUNT_ID` is required!"), - }; - CloudflareAuth::new(creds) -} - -#[cfg(feature = "backend-admin")] -fn init_admin_canisters() -> hot_or_not_web_leptos_ssr::state::admin_canisters::AdminCanisters { - use hot_or_not_web_leptos_ssr::state::admin_canisters::AdminCanisters; - use ic_agent::identity::BasicIdentity; - - let admin_id_pem = - env::var("BACKEND_ADMIN_IDENTITY").expect("`BACKEND_ADMIN_IDENTITY` is required!"); - let admin_id_pem_by = admin_id_pem.as_bytes(); - let admin_id = - BasicIdentity::from_pem(admin_id_pem_by).expect("Invalid `BACKEND_ADMIN_IDENTITY`"); - AdminCanisters::new(admin_id) -} - -async fn init_kv() -> KVStoreImpl { - #[cfg(feature = "redis-kv")] - { - use hot_or_not_web_leptos_ssr::auth::server_impl::store::redis_kv::RedisKV; - let redis_url = env::var("REDIS_URL").expect("`REDIS_URL` is required!"); - KVStoreImpl::Redis(RedisKV::new(&redis_url).await.unwrap()) - } - - #[cfg(not(feature = "redis-kv"))] - { - use hot_or_not_web_leptos_ssr::auth::server_impl::store::redb_kv::ReDBKV; - KVStoreImpl::ReDB(ReDBKV::new().expect("Failed to initialize ReDB")) - } -} - -fn init_cookie_key() -> Key { - let cookie_key_str = env::var("COOKIE_KEY").expect("`COOKIE_KEY` is required!"); - let cookie_key_raw = - hex::decode(cookie_key_str).expect("Invalid `COOKIE_KEY` (must be length 128 hex)"); - Key::from(&cookie_key_raw) -} - -#[cfg(feature = "oauth-ssr")] -fn init_google_oauth() -> openidconnect::core::CoreClient { - use hot_or_not_web_leptos_ssr::consts::google::{ - GOOGLE_AUTH_URL, GOOGLE_ISSUER_URL, GOOGLE_TOKEN_URL, - }; - use openidconnect::{ - core::CoreClient, AuthUrl, ClientId, ClientSecret, IssuerUrl, RedirectUrl, TokenUrl, - }; - - let client_id = env::var("GOOGLE_CLIENT_ID").expect("`GOOGLE_CLIENT_ID` is required!"); - let client_secret = - env::var("GOOGLE_CLIENT_SECRET").expect("`GOOGLE_CLIENT_SECRET` is required!"); - let redirect_uri = env::var("GOOGLE_REDIRECT_URL").expect("`GOOGLE_REDIRECT_URL` is required!"); - - CoreClient::new( - ClientId::new(client_id), - Some(ClientSecret::new(client_secret)), - IssuerUrl::new(GOOGLE_ISSUER_URL.to_string()).unwrap(), - AuthUrl::new(GOOGLE_AUTH_URL.to_string()).unwrap(), - Some(TokenUrl::new(GOOGLE_TOKEN_URL.to_string()).unwrap()), - None, - // We don't validate id_tokens against Google's public keys - Default::default(), - ) - .set_redirect_uri(RedirectUrl::new(redirect_uri).unwrap()) -} - -#[cfg(feature = "ga4")] -async fn init_grpc_offchain_channel() -> tonic::transport::Channel { - use tonic::transport::Channel; - - let off_chain_agent_url = OFF_CHAIN_AGENT_GRPC_URL.as_ref(); - Channel::from_static(off_chain_agent_url) - .connect() - .await - .expect("Couldn't connect to off-chain agent") -} - #[tokio::main] async fn main() { simple_logger::init_with_level(log::Level::Debug).expect("couldn't initialize logging"); @@ -166,20 +77,40 @@ async fn main() { let addr = leptos_options.site_addr; let routes = generate_route_list(App); - let app_state = AppState { - leptos_options, - canisters: Canisters::default(), - routes: routes.clone(), - #[cfg(feature = "backend-admin")] - admin_canisters: init_admin_canisters(), - #[cfg(feature = "cloudflare")] - cloudflare: init_cf(), - kv: init_kv().await, - cookie_key: init_cookie_key(), - #[cfg(feature = "oauth-ssr")] - google_oauth: init_google_oauth(), - #[cfg(feature = "ga4")] - grpc_offchain_channel: init_grpc_offchain_channel().await, + let res = AppStateBuilder::new(leptos_options, routes.clone()) + .build() + .await; + let terminate = { + use tokio::signal; + + let ctrl_c = async { + signal::ctrl_c() + .await + .expect("failed to install Ctrl+C handler"); + }; + + #[cfg(unix)] + let terminate = async { + use tokio::signal; + signal::unix::signal(signal::unix::SignalKind::terminate()) + .expect("failed to install signal handler") + .recv() + .await; + }; + + #[cfg(not(unix))] + let terminate = std::future::pending::<()>(); + + async { + tokio::select! { + _ = ctrl_c => {}, + _ = terminate => {}, + } + log::info!("stopping..."); + + #[cfg(feature = "local-bin")] + std::mem::drop(res.containers); + } }; // build our application with a route @@ -190,13 +121,14 @@ async fn main() { ) .leptos_routes_with_handler(routes, get(leptos_routes_handler)) .fallback(file_and_error_handler) - .with_state(app_state); + .with_state(res.app_state); // run our app with hyper // `axum::Server` is a re-export of `hyper::Server` log::info!("listening on http://{}", &addr); let listener = tokio::net::TcpListener::bind(&addr).await.unwrap(); axum::serve(listener, app.into_make_service()) + .with_graceful_shutdown(terminate) .await .unwrap(); } diff --git a/src/state/admin_canisters.rs b/src/state/admin_canisters.rs index b6ebd081..16cd2e6f 100644 --- a/src/state/admin_canisters.rs +++ b/src/state/admin_canisters.rs @@ -2,9 +2,8 @@ use candid::Principal; use ic_agent::Identity; use leptos::expect_context; -use crate::canister::{ - individual_user_template::IndividualUserTemplate, user_index::UserIndex, AGENT_URL, -}; +use super::canisters::build_agent; +use crate::canister::{individual_user_template::IndividualUserTemplate, user_index::UserIndex}; #[derive(Clone)] pub struct AdminCanisters { @@ -14,11 +13,7 @@ pub struct AdminCanisters { impl AdminCanisters { pub fn new(key: impl Identity + 'static) -> Self { Self { - agent: ic_agent::Agent::builder() - .with_url(AGENT_URL) - .with_identity(key) - .build() - .unwrap(), + agent: build_agent(|b| b.with_identity(key)), } } diff --git a/src/state/canisters.rs b/src/state/canisters.rs index 60718311..176dd43b 100644 --- a/src/state/canisters.rs +++ b/src/state/canisters.rs @@ -1,7 +1,7 @@ -use std::{collections::HashSet, sync::Arc}; +use std::sync::Arc; use candid::Principal; -use ic_agent::{identity::DelegatedIdentity, AgentError, Identity}; +use ic_agent::{agent::AgentBuilder, identity::DelegatedIdentity, AgentError, Identity}; use leptos::*; use yral_metadata_client::MetadataClient; use yral_metadata_types::UserMetadata; @@ -10,15 +10,41 @@ use crate::{ auth::DelegatedIdentityWire, canister::{ individual_user_template::{IndividualUserTemplate, Result9, UserCanisterDetails}, - platform_orchestrator::{self, PlatformOrchestrator}, - post_cache::{self, PostCache}, + platform_orchestrator::PlatformOrchestrator, + post_cache::PostCache, user_index::UserIndex, - AGENT_URL, + PLATFORM_ORCHESTRATOR_ID, POST_CACHE_ID, }, - consts::METADATA_API_BASE, + consts::{AGENT_URL, METADATA_API_BASE}, utils::{profile::ProfileDetails, MockPartialEq}, }; +pub fn build_agent(builder_func: impl FnOnce(AgentBuilder) -> AgentBuilder) -> ic_agent::Agent { + let mut builder = ic_agent::Agent::builder().with_url(AGENT_URL); + + builder = builder_func(builder); + #[cfg(any(feature = "local-bin", feature = "local-lib"))] + { + builder = builder.with_verify_query_signatures(false); + let agent = builder.build().unwrap(); + // TODO: this is specific to the local environment + agent.set_root_key(Vec::from([ + 48, 129, 130, 48, 29, 6, 13, 43, 6, 1, 4, 1, 130, 220, 124, 5, 3, 1, 2, 1, 6, 12, 43, + 6, 1, 4, 1, 130, 220, 124, 5, 3, 2, 1, 3, 97, 0, 177, 245, 178, 217, 104, 189, 171, + 227, 105, 94, 61, 178, 63, 151, 4, 117, 247, 115, 131, 226, 98, 62, 205, 43, 78, 42, 7, + 213, 13, 11, 186, 34, 7, 14, 23, 23, 196, 62, 83, 237, 220, 71, 19, 60, 44, 9, 152, 36, + 25, 96, 126, 153, 75, 232, 77, 136, 196, 241, 4, 243, 202, 21, 52, 235, 136, 5, 178, + 138, 210, 174, 215, 93, 253, 250, 164, 233, 106, 176, 111, 133, 142, 165, 125, 25, 82, + 136, 150, 165, 108, 198, 152, 49, 68, 168, 10, 40, + ])); + agent + } + #[cfg(not(any(feature = "local-bin", feature = "local-lib")))] + { + builder.build().unwrap() + } +} + #[derive(Clone)] pub struct Canisters { agent: ic_agent::Agent, @@ -32,10 +58,7 @@ pub struct Canisters { impl Default for Canisters { fn default() -> Self { Self { - agent: ic_agent::Agent::builder() - .with_url(AGENT_URL) - .build() - .unwrap(), + agent: build_agent(|b| b), id: None, metadata_client: MetadataClient::with_base_url(METADATA_API_BASE.clone()), user_canister: Principal::anonymous(), @@ -56,11 +79,7 @@ impl Canisters { let id = Arc::new(id); Canisters { - agent: ic_agent::Agent::builder() - .with_url(AGENT_URL) - .with_arc_identity(id.clone()) - .build() - .unwrap(), + agent: build_agent(|b| b.with_arc_identity(id.clone())), metadata_client: MetadataClient::with_base_url(METADATA_API_BASE.clone()), id: Some(id), user_canister: Principal::anonymous(), @@ -96,7 +115,7 @@ impl Canisters { impl Canisters { pub fn post_cache(&self) -> PostCache<'_> { - PostCache(post_cache::CANISTER_ID, &self.agent) + PostCache(POST_CACHE_ID, &self.agent) } pub fn individual_user(&self, user_canister: Principal) -> IndividualUserTemplate<'_> { @@ -108,7 +127,7 @@ impl Canisters { } pub fn orchestrator(&self) -> PlatformOrchestrator<'_> { - PlatformOrchestrator(platform_orchestrator::CANISTER_ID, &self.agent) + PlatformOrchestrator(PLATFORM_ORCHESTRATOR_ID, &self.agent) } pub async fn get_individual_canister_by_user_principal( @@ -123,16 +142,25 @@ impl Canisters { } async fn subnet_indexes(&self) -> Result, AgentError> { - // TODO: this is temporary - let blacklisted = - HashSet::from([Principal::from_text("rimrc-piaaa-aaaao-aaljq-cai").unwrap()]); - let orchestrator = self.orchestrator(); - Ok(orchestrator - .get_all_available_subnet_orchestrators() - .await? - .into_iter() - .filter(|subnet| !blacklisted.contains(subnet)) - .collect()) + #[cfg(any(feature = "local-bin", feature = "local-lib"))] + { + use crate::canister::USER_INDEX_ID; + Ok(vec![USER_INDEX_ID]) + } + #[cfg(not(any(feature = "local-bin", feature = "local-lib")))] + { + use std::collections::HashSet; + // TODO: this is temporary + let blacklisted = + HashSet::from([Principal::from_text("rimrc-piaaa-aaaao-aaljq-cai").unwrap()]); + let orchestrator = self.orchestrator(); + Ok(orchestrator + .get_all_available_subnet_orchestrators() + .await? + .into_iter() + .filter(|subnet| !blacklisted.contains(subnet)) + .collect()) + } } } From f2e135fbd9d1ffc117c1630ac9b4b3a0bacda898 Mon Sep 17 00:00:00 2001 From: rupansh Date: Mon, 15 Jul 2024 03:48:38 +0530 Subject: [PATCH 2/8] fix(state/canisters): use ic-agent fork for auto fetching root keys --- Cargo.lock | 77 +++++++++++++++++++++++++++++++++++------- Cargo.toml | 9 +++-- src/state/canisters.rs | 20 ++++------- 3 files changed, 77 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f762190c..3c91c146 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,6 +128,17 @@ dependencies = [ "term", ] +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + [[package]] name = "async-recursion" version = "1.1.1" @@ -828,6 +839,15 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "config" version = "0.14.0" @@ -948,6 +968,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + [[package]] name = "crunchy" version = "0.2.2" @@ -1399,6 +1425,27 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener", + "pin-project-lite", +] + [[package]] name = "faster-hex" version = "0.9.0" @@ -2880,10 +2927,10 @@ dependencies = [ [[package]] name = "ic-agent" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555eda283b8ba1a996d44d80b6c9a6d38a6cbb81797a7b7bbee134fdde64ce48" +version = "0.36.0" +source = "git+https://github.com/rupansh/agent-rs?rev=8e60e04fbdfaff6dbcf006843a86038d561aab95#8e60e04fbdfaff6dbcf006843a86038d561aab95" dependencies = [ + "async-lock", "backoff", "cached 0.46.1", "candid", @@ -2904,7 +2951,7 @@ dependencies = [ "pkcs8", "rand", "rangemap", - "reqwest 0.11.27", + "reqwest 0.12.5", "ring", "rustls-webpki 0.101.7", "sec1", @@ -2937,9 +2984,8 @@ dependencies = [ [[package]] name = "ic-transport-types" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c06d3c1292368c813f8104d9d8294bda5577ea6fe4501a65997d0b7f155f15f" +version = "0.36.0" +source = "git+https://github.com/rupansh/agent-rs?rev=8e60e04fbdfaff6dbcf006843a86038d561aab95#8e60e04fbdfaff6dbcf006843a86038d561aab95" dependencies = [ "candid", "hex", @@ -4159,6 +4205,12 @@ dependencies = [ "group 0.12.1", ] +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + [[package]] name = "parking_lot" version = "0.12.3" @@ -4794,12 +4846,10 @@ dependencies = [ "system-configuration", "tokio", "tokio-rustls 0.24.1", - "tokio-util", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", "web-sys", "webpki-roots 0.25.4", "winreg 0.50.0", @@ -4814,6 +4864,7 @@ dependencies = [ "base64 0.22.1", "bytes", "encoding_rs", + "futures-channel", "futures-core", "futures-util", "h2 0.4.5", @@ -4846,10 +4897,12 @@ dependencies = [ "tokio", "tokio-native-tls", "tokio-rustls 0.26.0", + "tokio-util", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams", "web-sys", "webpki-roots 0.26.1", "winreg 0.52.0", @@ -6645,7 +6698,7 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yral-identity" version = "0.1.0" -source = "git+https://github.com/go-bazzinga/yral-identity.git?rev=346f61f5bf07b619be8dfc3d041dc665c4c66113#346f61f5bf07b619be8dfc3d041dc665c4c66113" +source = "git+https://github.com/go-bazzinga/yral-identity.git?rev=6df2ed46e422302cb47d22ce30927756ee531a66#6df2ed46e422302cb47d22ce30927756ee531a66" dependencies = [ "candid", "ic-agent", @@ -6657,7 +6710,7 @@ dependencies = [ [[package]] name = "yral-metadata-client" version = "0.1.0" -source = "git+https://github.com/go-bazzinga/yral-metadata?rev=c2c5d254ac273681a66966d62b6f01785679a1be#c2c5d254ac273681a66966d62b6f01785679a1be" +source = "git+https://github.com/go-bazzinga/yral-metadata?rev=c394bf9af3f32d81c1ac50b966c25dafafa2545b#c394bf9af3f32d81c1ac50b966c25dafafa2545b" dependencies = [ "ic-agent", "reqwest 0.12.5", @@ -6669,7 +6722,7 @@ dependencies = [ [[package]] name = "yral-metadata-types" version = "0.1.0" -source = "git+https://github.com/go-bazzinga/yral-metadata?rev=c2c5d254ac273681a66966d62b6f01785679a1be#c2c5d254ac273681a66966d62b6f01785679a1be" +source = "git+https://github.com/go-bazzinga/yral-metadata?rev=c394bf9af3f32d81c1ac50b966c25dafafa2545b#c394bf9af3f32d81c1ac50b966c25dafafa2545b" dependencies = [ "candid", "serde", diff --git a/Cargo.toml b/Cargo.toml index 51816e06..6cd3ac1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ tracing = { version = "0.1.37", optional = true } http = "1.1.0" serde = { version = "1.0", features = ["derive"] } candid = "0.10.3" -ic-agent = { version = "0.34.0", default-features = false, features = [ +ic-agent = { version = "0.36.0", default-features = false, features = [ "pem", "reqwest", ] } @@ -82,8 +82,8 @@ redis = { version = "0.25.2", features = [ bb8 = { version = "0.8.3", optional = true } bb8-redis = { version = "0.15.0", optional = true } gob-cloudflare = { git = "https://github.com/go-bazzinga/gob-cloudflare", rev = "c847ba87ecc73a33520b24bd62503420d7e23e3e", default-features = false, optional = true } -yral-metadata-client = { git = "https://github.com/go-bazzinga/yral-metadata", rev = "c2c5d254ac273681a66966d62b6f01785679a1be", default-features = false } -yral-metadata-types = { git = "https://github.com/go-bazzinga/yral-metadata", rev = "c2c5d254ac273681a66966d62b6f01785679a1be", default-features = false } +yral-metadata-client = { git = "https://github.com/go-bazzinga/yral-metadata", rev = "c394bf9af3f32d81c1ac50b966c25dafafa2545b", default-features = false } +yral-metadata-types = { git = "https://github.com/go-bazzinga/yral-metadata", rev = "c394bf9af3f32d81c1ac50b966c25dafafa2545b", default-features = false } gloo-utils = { version = "0.2.0", features = ["serde"] } tonic = { version = "0.11.0", features = [ "tls", @@ -94,6 +94,9 @@ hmac = { version = "0.12.1", optional = true } testcontainers = { version = "0.20.0", optional = true } yral-testcontainers = { git = "https://github.com/go-bazzinga/yral-testcontainers", rev = "14740097702fbc925ec2dbaa2b4a7660775576f4", optional = true } +[patch.crates-io] +ic-agent = { git = "https://github.com/rupansh/agent-rs", rev = "8e60e04fbdfaff6dbcf006843a86038d561aab95" } + [build-dependencies] serde = { version = "1.0", features = ["derive"] } candid_parser = "0.1.1" diff --git a/src/state/canisters.rs b/src/state/canisters.rs index 176dd43b..f04524cf 100644 --- a/src/state/canisters.rs +++ b/src/state/canisters.rs @@ -25,19 +25,11 @@ pub fn build_agent(builder_func: impl FnOnce(AgentBuilder) -> AgentBuilder) -> i builder = builder_func(builder); #[cfg(any(feature = "local-bin", feature = "local-lib"))] { - builder = builder.with_verify_query_signatures(false); - let agent = builder.build().unwrap(); - // TODO: this is specific to the local environment - agent.set_root_key(Vec::from([ - 48, 129, 130, 48, 29, 6, 13, 43, 6, 1, 4, 1, 130, 220, 124, 5, 3, 1, 2, 1, 6, 12, 43, - 6, 1, 4, 1, 130, 220, 124, 5, 3, 2, 1, 3, 97, 0, 177, 245, 178, 217, 104, 189, 171, - 227, 105, 94, 61, 178, 63, 151, 4, 117, 247, 115, 131, 226, 98, 62, 205, 43, 78, 42, 7, - 213, 13, 11, 186, 34, 7, 14, 23, 23, 196, 62, 83, 237, 220, 71, 19, 60, 44, 9, 152, 36, - 25, 96, 126, 153, 75, 232, 77, 136, 196, 241, 4, 243, 202, 21, 52, 235, 136, 5, 178, - 138, 210, 174, 215, 93, 253, 250, 164, 233, 106, 176, 111, 133, 142, 165, 125, 25, 82, - 136, 150, 165, 108, 198, 152, 49, 68, 168, 10, 40, - ])); - agent + builder = builder + .with_verify_query_signatures(false) + .with_auto_fetch_root_key(true); + + builder.build().unwrap() } #[cfg(not(any(feature = "local-bin", feature = "local-lib")))] { @@ -49,7 +41,7 @@ pub fn build_agent(builder_func: impl FnOnce(AgentBuilder) -> AgentBuilder) -> i pub struct Canisters { agent: ic_agent::Agent, id: Option>, - metadata_client: MetadataClient, + metadata_client: MetadataClient, user_canister: Principal, expiry: u64, profile_details: Option, From b0bed58efb9c4d5a119e145b3c7c3c538b396c97 Mon Sep 17 00:00:00 2001 From: rupansh Date: Mon, 22 Jul 2024 21:38:56 +0530 Subject: [PATCH 3/8] refactor: switch back to crates.io ic-agent --- Cargo.lock | 6 ++- Cargo.toml | 3 -- src/component/auth_providers/mod.rs | 10 +++-- src/page/post_view/overlay.rs | 4 +- src/page/post_view/video_iter.rs | 4 +- src/page/post_view/video_loader.rs | 2 + src/page/profile/mod.rs | 2 +- src/page/profile/profile_iter.rs | 2 +- src/page/profile/speculation.rs | 4 +- src/page/refer_earn/history.rs | 2 +- src/page/root.rs | 2 +- src/page/upload/cf_upload.rs | 2 +- src/page/wallet/mod.rs | 8 +++- src/page/wallet/txn.rs | 2 +- src/state/admin_canisters.rs | 28 ++++++++---- src/state/canisters.rs | 66 +++++++++++++---------------- src/utils/ic.rs | 23 ++++++++++ src/utils/mod.rs | 1 + src/utils/posts.rs | 2 +- src/utils/profile.rs | 4 +- 20 files changed, 106 insertions(+), 71 deletions(-) create mode 100644 src/utils/ic.rs diff --git a/Cargo.lock b/Cargo.lock index 3c91c146..00d11ec6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2928,7 +2928,8 @@ dependencies = [ [[package]] name = "ic-agent" version = "0.36.0" -source = "git+https://github.com/rupansh/agent-rs?rev=8e60e04fbdfaff6dbcf006843a86038d561aab95#8e60e04fbdfaff6dbcf006843a86038d561aab95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba85280257d8663adef20bf5c043b287b3a283d4f916073eb3ca9166a4a59d4b" dependencies = [ "async-lock", "backoff", @@ -2985,7 +2986,8 @@ dependencies = [ [[package]] name = "ic-transport-types" version = "0.36.0" -source = "git+https://github.com/rupansh/agent-rs?rev=8e60e04fbdfaff6dbcf006843a86038d561aab95#8e60e04fbdfaff6dbcf006843a86038d561aab95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce14c068bd053c0f5ab525326f3f358f265cdfcae279fbf6461fb529e9682acd" dependencies = [ "candid", "hex", diff --git a/Cargo.toml b/Cargo.toml index 6cd3ac1d..d9b7e5a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,9 +94,6 @@ hmac = { version = "0.12.1", optional = true } testcontainers = { version = "0.20.0", optional = true } yral-testcontainers = { git = "https://github.com/go-bazzinga/yral-testcontainers", rev = "14740097702fbc925ec2dbaa2b4a7660775576f4", optional = true } -[patch.crates-io] -ic-agent = { git = "https://github.com/rupansh/agent-rs", rev = "8e60e04fbdfaff6dbcf006843a86038d561aab95" } - [build-dependencies] serde = { version = "1.0", features = ["derive"] } candid_parser = "0.1.1" diff --git a/src/component/auth_providers/mod.rs b/src/component/auth_providers/mod.rs index b03dd936..d7a751b3 100644 --- a/src/component/auth_providers/mod.rs +++ b/src/component/auth_providers/mod.rs @@ -200,14 +200,16 @@ mod server_fn_impl { referee_canister: Principal, ) -> Result<(), ServerFnError> { let canisters = unauth_canisters(); - let user = canisters.individual_user(referee_canister); + let user = canisters.individual_user(referee_canister).await?; let referrer_details = user .get_profile_details() .await? .referrer_details .ok_or(ServerFnError::new("Referrer details not found"))?; - let referrer = canisters.individual_user(referrer_details.user_canister_id); + let referrer = canisters + .individual_user(referrer_details.user_canister_id) + .await?; let user_details = user.get_profile_details().await?; @@ -247,7 +249,7 @@ mod server_fn_impl { use crate::{canister::user_index::Result_, state::admin_canisters::admin_canisters}; let admin_cans = admin_canisters(); - let user_idx = admin_cans.user_index_with(user_index); + let user_idx = admin_cans.user_index_with(user_index).await?; let res = user_idx .issue_rewards_for_referral( user_canister_id, @@ -272,7 +274,7 @@ mod server_fn_impl { }; let admin_cans = admin_canisters(); - let user = admin_cans.individual_user_for(user_canister); + let user = admin_cans.individual_user_for(user_canister).await?; if matches!( user.get_session_type().await?, Result6::Ok(SessionType::RegisteredSession) diff --git a/src/page/post_view/overlay.rs b/src/page/post_view/overlay.rs index f6196434..c37b7e33 100644 --- a/src/page/post_view/overlay.rs +++ b/src/page/post_view/overlay.rs @@ -62,7 +62,9 @@ fn LikeAndAuthCanLoader(post: PostDetails) -> impl IntoView { LikeVideo.send_event(post_details, likes, canister_store); } }); - let individual = canisters.individual_user(post_canister); + let Ok(individual) = canisters.individual_user(post_canister).await else { + return; + }; match individual .update_post_toggle_like_status_by_caller(post_id) .await diff --git a/src/page/post_view/video_iter.rs b/src/page/post_view/video_iter.rs index 391b3724..f4a768d6 100644 --- a/src/page/post_view/video_iter.rs +++ b/src/page/post_view/video_iter.rs @@ -14,7 +14,7 @@ pub async fn post_liked_by_me( post_canister: Principal, post_id: u64, ) -> Result { - let individual = canisters.individual_user(post_canister); + let individual = canisters.individual_user(post_canister).await?; let post = individual .get_individual_post_details_by_id(post_id) .await?; @@ -43,7 +43,7 @@ impl<'a, const AUTH: bool> VideoFetchStream<'a, AUTH> { chunks: usize, allow_nsfw: bool, ) -> Result, PostViewError> { - let post_cache = self.canisters.post_cache(); + let post_cache = self.canisters.post_cache().await?; let top_posts_fut = post_cache .get_top_posts_aggregated_from_canisters_on_this_network_for_home_feed_cursor( self.cursor.start, diff --git a/src/page/post_view/video_loader.rs b/src/page/post_view/video_loader.rs index 4dfee011..e931a441 100644 --- a/src/page/post_view/video_loader.rs +++ b/src/page/post_view/video_loader.rs @@ -150,6 +150,8 @@ pub fn VideoView( .unwrap(); let send_view_res = canisters .individual_user(canister_id) + .await + .ok()? .update_post_add_view_details(post_id, payload) .await; diff --git a/src/page/profile/mod.rs b/src/page/profile/mod.rs index a838577b..4aa02ec3 100644 --- a/src/page/profile/mod.rs +++ b/src/page/profile/mod.rs @@ -155,7 +155,7 @@ pub fn ProfileView() -> impl IntoView { .get_individual_canister_by_user_principal(principal?) .await .ok()??; - let user = canisters.individual_user(user_canister); + let user = canisters.individual_user(user_canister).await.ok()?; let user_details = user.get_profile_details().await.ok()?; Some((user_details.into(), user_canister)) }); diff --git a/src/page/profile/profile_iter.rs b/src/page/profile/profile_iter.rs index a029dd38..1b564ea9 100644 --- a/src/page/profile/profile_iter.rs +++ b/src/page/profile/profile_iter.rs @@ -26,7 +26,7 @@ impl<'a, const AUTH: bool> ProfileVideoStream<'a, AUTH> { } pub async fn fetch_next_profile_posts(&self) -> Result, PostViewError> { - let user = self.canisters.individual_user(self.user_canister); + let user = self.canisters.individual_user(self.user_canister).await?; let posts = user .get_posts_of_this_user_profile_with_pagination_cursor( self.cursor.start, diff --git a/src/page/profile/speculation.rs b/src/page/profile/speculation.rs index d5a056a7..ff4a8ba1 100644 --- a/src/page/profile/speculation.rs +++ b/src/page/profile/speculation.rs @@ -111,7 +111,7 @@ pub fn Speculation(details: BetDetails, _ref: NodeRef) -> impl IntoVi move || details.canister_id, move |canister_id| async move { let canister = unauth_canisters(); - let user = canister.individual_user(canister_id); + let user = canister.individual_user(canister_id).await.ok()?; let profile_details = user.get_profile_details().await.ok()?; Some(ProfileDetails::from(profile_details)) }, @@ -120,7 +120,7 @@ pub fn Speculation(details: BetDetails, _ref: NodeRef) -> impl IntoVi move || (details.canister_id, details.post_id), move |(canister_id, post_id)| async move { let canister = unauth_canisters(); - let user = canister.individual_user(canister_id); + let user = canister.individual_user(canister_id).await.ok()?; let post_details = user.get_individual_post_details_by_id(post_id).await.ok()?; Some(PostDetails::from_canister_post( false, diff --git a/src/page/refer_earn/history.rs b/src/page/refer_earn/history.rs index 62928936..e4198177 100644 --- a/src/page/refer_earn/history.rs +++ b/src/page/refer_earn/history.rs @@ -114,7 +114,7 @@ mod history_provider { ) -> Result, AgentError> { use crate::canister::individual_user_template::{MintEvent, Result7, TokenEvent}; use crate::utils::route::failure_redirect; - let individual = self.0.authenticated_user(); + let individual = self.0.authenticated_user().await?; let history = individual .get_user_utility_token_transaction_history_with_pagination( from as u64, diff --git a/src/page/root.rs b/src/page/root.rs index 23bc8e10..ff8d437a 100644 --- a/src/page/root.rs +++ b/src/page/root.rs @@ -9,7 +9,7 @@ use crate::{canister::post_cache, state::canisters::unauth_canisters}; #[server] async fn get_top_post_id() -> Result, ServerFnError> { let canisters = unauth_canisters(); - let post_cache = canisters.post_cache(); + let post_cache = canisters.post_cache().await?; let top_items = match post_cache .get_top_posts_aggregated_from_canisters_on_this_network_for_home_feed_cursor( diff --git a/src/page/upload/cf_upload.rs b/src/page/upload/cf_upload.rs index 4cc079cc..aa139f3d 100644 --- a/src/page/upload/cf_upload.rs +++ b/src/page/upload/cf_upload.rs @@ -129,7 +129,7 @@ mod cf_impl { enable_hot_or_not: bool, is_nsfw: bool, ) -> Result<(), ServerFnError> { - let user = canisters.authenticated_user(); + let user = canisters.authenticated_user().await?; let res = user .add_post_v_2(PostDetailsFromFrontend { hashtags, diff --git a/src/page/wallet/mod.rs b/src/page/wallet/mod.rs index 627ff66e..65a2ddfa 100644 --- a/src/page/wallet/mod.rs +++ b/src/page/wallet/mod.rs @@ -58,7 +58,9 @@ fn BalanceFetch(cans: Canisters) -> impl IntoView { move |_| { let canisters = cans.clone(); async move { - let user = canisters.authenticated_user(); + let Ok(user) = canisters.authenticated_user().await else { + return "Error".to_string(); + }; user.get_utility_token_balance() .await @@ -80,7 +82,9 @@ pub fn Wallet() -> impl IntoView { let (is_connected, _) = account_connected_reader(); let balance_fetch = |cans: Canisters| async move { - let user = cans.authenticated_user(); + let Ok(user) = cans.authenticated_user().await else { + return "Error".to_string(); + }; user.get_utility_token_balance() .await diff --git a/src/page/wallet/txn.rs b/src/page/wallet/txn.rs index ad5740ab..d2f957c4 100644 --- a/src/page/wallet/txn.rs +++ b/src/page/wallet/txn.rs @@ -205,7 +205,7 @@ pub mod provider { start: usize, end: usize, ) -> Result, AgentError> { - let user = self.0.authenticated_user(); + let user = self.0.authenticated_user().await?; let history = user .get_user_utility_token_transaction_history_with_pagination( start as u64, diff --git a/src/state/admin_canisters.rs b/src/state/admin_canisters.rs index 16cd2e6f..d5cac21b 100644 --- a/src/state/admin_canisters.rs +++ b/src/state/admin_canisters.rs @@ -1,28 +1,38 @@ use candid::Principal; -use ic_agent::Identity; +use ic_agent::{AgentError, Identity}; use leptos::expect_context; -use super::canisters::build_agent; -use crate::canister::{individual_user_template::IndividualUserTemplate, user_index::UserIndex}; +use crate::{ + canister::{individual_user_template::IndividualUserTemplate, user_index::UserIndex}, + utils::ic::AgentWrapper, +}; #[derive(Clone)] pub struct AdminCanisters { - agent: ic_agent::Agent, + agent: AgentWrapper, } impl AdminCanisters { pub fn new(key: impl Identity + 'static) -> Self { Self { - agent: build_agent(|b| b.with_identity(key)), + agent: AgentWrapper::build(|b| b.with_identity(key)), } } - pub fn user_index_with(&self, idx_principal: Principal) -> UserIndex<'_> { - UserIndex(idx_principal, &self.agent) + pub async fn user_index_with( + &self, + idx_principal: Principal, + ) -> Result, AgentError> { + let agent = self.agent.get_agent().await?; + Ok(UserIndex(idx_principal, agent)) } - pub fn individual_user_for(&self, user_canister: Principal) -> IndividualUserTemplate<'_> { - IndividualUserTemplate(user_canister, &self.agent) + pub async fn individual_user_for( + &self, + user_canister: Principal, + ) -> Result, AgentError> { + let agent = self.agent.get_agent().await?; + Ok(IndividualUserTemplate(user_canister, agent)) } } diff --git a/src/state/canisters.rs b/src/state/canisters.rs index f04524cf..24929792 100644 --- a/src/state/canisters.rs +++ b/src/state/canisters.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use candid::Principal; -use ic_agent::{agent::AgentBuilder, identity::DelegatedIdentity, AgentError, Identity}; +use ic_agent::{identity::DelegatedIdentity, AgentError, Identity}; use leptos::*; use yral_metadata_client::MetadataClient; use yral_metadata_types::UserMetadata; @@ -15,31 +15,13 @@ use crate::{ user_index::UserIndex, PLATFORM_ORCHESTRATOR_ID, POST_CACHE_ID, }, - consts::{AGENT_URL, METADATA_API_BASE}, - utils::{profile::ProfileDetails, MockPartialEq}, + consts::METADATA_API_BASE, + utils::{ic::AgentWrapper, profile::ProfileDetails, MockPartialEq}, }; -pub fn build_agent(builder_func: impl FnOnce(AgentBuilder) -> AgentBuilder) -> ic_agent::Agent { - let mut builder = ic_agent::Agent::builder().with_url(AGENT_URL); - - builder = builder_func(builder); - #[cfg(any(feature = "local-bin", feature = "local-lib"))] - { - builder = builder - .with_verify_query_signatures(false) - .with_auto_fetch_root_key(true); - - builder.build().unwrap() - } - #[cfg(not(any(feature = "local-bin", feature = "local-lib")))] - { - builder.build().unwrap() - } -} - #[derive(Clone)] pub struct Canisters { - agent: ic_agent::Agent, + agent: AgentWrapper, id: Option>, metadata_client: MetadataClient, user_canister: Principal, @@ -50,7 +32,7 @@ pub struct Canisters { impl Default for Canisters { fn default() -> Self { Self { - agent: build_agent(|b| b), + agent: AgentWrapper::build(|b| b), id: None, metadata_client: MetadataClient::with_base_url(METADATA_API_BASE.clone()), user_canister: Principal::anonymous(), @@ -71,7 +53,7 @@ impl Canisters { let id = Arc::new(id); Canisters { - agent: build_agent(|b| b.with_arc_identity(id.clone())), + agent: AgentWrapper::build(|b| b.with_arc_identity(id.clone())), metadata_client: MetadataClient::with_base_url(METADATA_API_BASE.clone()), id: Some(id), user_canister: Principal::anonymous(), @@ -94,8 +76,8 @@ impl Canisters { self.user_canister } - pub fn authenticated_user(&self) -> IndividualUserTemplate<'_> { - IndividualUserTemplate(self.user_canister, &self.agent) + pub async fn authenticated_user(&self) -> Result, AgentError> { + self.individual_user(self.user_canister).await } pub fn profile_details(&self) -> ProfileDetails { @@ -106,20 +88,30 @@ impl Canisters { } impl Canisters { - pub fn post_cache(&self) -> PostCache<'_> { - PostCache(POST_CACHE_ID, &self.agent) + pub async fn post_cache(&self) -> Result, AgentError> { + let agent = self.agent.get_agent().await?; + Ok(PostCache(POST_CACHE_ID, agent)) } - pub fn individual_user(&self, user_canister: Principal) -> IndividualUserTemplate<'_> { - IndividualUserTemplate(user_canister, &self.agent) + pub async fn individual_user( + &self, + user_canister: Principal, + ) -> Result, AgentError> { + let agent = self.agent.get_agent().await?; + Ok(IndividualUserTemplate(user_canister, agent)) } - pub fn user_index_with(&self, subnet_principal: Principal) -> UserIndex<'_> { - UserIndex(subnet_principal, &self.agent) + pub async fn user_index_with( + &self, + subnet_principal: Principal, + ) -> Result, AgentError> { + let agent = self.agent.get_agent().await?; + Ok(UserIndex(subnet_principal, agent)) } - pub fn orchestrator(&self) -> PlatformOrchestrator<'_> { - PlatformOrchestrator(PLATFORM_ORCHESTRATOR_ID, &self.agent) + pub async fn orchestrator(&self) -> Result, AgentError> { + let agent = self.agent.get_agent().await?; + Ok(PlatformOrchestrator(PLATFORM_ORCHESTRATOR_ID, agent)) } pub async fn get_individual_canister_by_user_principal( @@ -145,7 +137,7 @@ impl Canisters { // TODO: this is temporary let blacklisted = HashSet::from([Principal::from_text("rimrc-piaaa-aaaao-aaljq-cai").unwrap()]); - let orchestrator = self.orchestrator(); + let orchestrator = self.orchestrator().await?; Ok(orchestrator .get_all_available_subnet_orchestrators() .await? @@ -173,7 +165,7 @@ async fn create_individual_canister( let discrim = u128::from_be_bytes(by); let subnet_idx = subnet_idxs[(discrim % subnet_idxs.len() as u128) as usize]; - let idx = canisters.user_index_with(subnet_idx); + let idx = canisters.user_index_with(subnet_idx).await?; let user_canister = idx .get_requester_principals_canister_id_create_if_not_exists_and_optionally_allow_referrer() .await?; @@ -208,7 +200,7 @@ pub async fn do_canister_auth( create_individual_canister(&canisters).await? }; - let user = canisters.authenticated_user(); + let user = canisters.authenticated_user().await?; if let Some(referrer_principal_id) = referrer { let referrer_canister = canisters diff --git a/src/utils/ic.rs b/src/utils/ic.rs new file mode 100644 index 00000000..da5ef997 --- /dev/null +++ b/src/utils/ic.rs @@ -0,0 +1,23 @@ +use ic_agent::{agent::AgentBuilder, Agent, AgentError}; + +use crate::consts::AGENT_URL; + +#[derive(Clone)] +pub struct AgentWrapper(Agent); + +impl AgentWrapper { + pub fn build(builder_func: impl FnOnce(AgentBuilder) -> AgentBuilder) -> Self { + let mut builder = Agent::builder().with_url(AGENT_URL); + builder = builder_func(builder); + Self(builder.build().unwrap()) + } + + pub async fn get_agent(&self) -> Result<&Agent, AgentError> { + let agent = &self.0; + #[cfg(any(feature = "local-bin", feature = "local-lib"))] + { + agent.fetch_root_key().await?; + } + Ok(agent) + } +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index c86febfe..ff0a5d89 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize}; use web_time::{Duration, SystemTime}; pub mod event_streaming; +pub mod ic; pub mod icon; pub mod posts; pub mod profile; diff --git a/src/utils/posts.rs b/src/utils/posts.rs index 3a9edf6e..47685184 100644 --- a/src/utils/posts.rs +++ b/src/utils/posts.rs @@ -95,7 +95,7 @@ pub async fn get_post_uid( user_canister: Principal, post_id: u64, ) -> Result, PostViewError> { - let post_creator_can = canisters.individual_user(user_canister); + let post_creator_can = canisters.individual_user(user_canister).await?; let post_details = match post_creator_can .get_individual_post_details_by_id(post_id) .await diff --git a/src/utils/profile.rs b/src/utils/profile.rs index 5782cfdb..19c95f75 100644 --- a/src/utils/profile.rs +++ b/src/utils/profile.rs @@ -177,7 +177,7 @@ impl CursoredDataProvider for PostsProvider { start: usize, end: usize, ) -> Result, AgentError> { - let user = self.canisters.individual_user(self.user); + let user = self.canisters.individual_user(self.user).await?; let limit = end - start; let posts = user .get_posts_of_this_user_profile_with_pagination_cursor(start as u64, limit as u64) @@ -229,7 +229,7 @@ impl CursoredDataProvider for BetsProvider { start: usize, end: usize, ) -> Result, AgentError> { - let user = self.canisters.individual_user(self.user); + let user = self.canisters.individual_user(self.user).await?; assert_eq!(end - start, 10); let bets = user .get_hot_or_not_bets_placed_by_this_profile_with_pagination(start as u64) From 4d1d4a3ef26a73722a5e427609b1db3cf0707f5d Mon Sep 17 00:00:00 2001 From: rupansh Date: Mon, 22 Jul 2024 21:54:55 +0530 Subject: [PATCH 4/8] fix: add local-run.sh for graceful exits --- local-run.sh | 4 ++++ 1 file changed, 4 insertions(+) create mode 100755 local-run.sh diff --git a/local-run.sh b/local-run.sh new file mode 100755 index 00000000..f8ec5a4e --- /dev/null +++ b/local-run.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +cargo leptos build --bin-features local-bin --lib-features local-lib +LEPTOS_SITE_ROOT="./target/site" LEPTOS_HASH_FILES=true ./target/debug/hot-or-not-web-leptos-ssr From 0f65cdfd981af98c0d3f32bb9fa3ac797d23f431 Mon Sep 17 00:00:00 2001 From: rupansh Date: Tue, 23 Jul 2024 00:21:49 +0530 Subject: [PATCH 5/8] fix(local): setup user_principal->canister mapping for admin principal --- Cargo.lock | 3 ++- Cargo.toml | 4 +++- local-run.sh | 2 +- src/init/containers.rs | 45 +++++++++++++++++++++++++++++++++++++++++- src/init/mod.rs | 31 +++++++++++++++++++++-------- 5 files changed, 73 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 00d11ec6..d90abfb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6735,10 +6735,11 @@ dependencies = [ [[package]] name = "yral-testcontainers" version = "0.1.0" -source = "git+https://github.com/go-bazzinga/yral-testcontainers?rev=14740097702fbc925ec2dbaa2b4a7660775576f4#14740097702fbc925ec2dbaa2b4a7660775576f4" +source = "git+https://github.com/go-bazzinga/yral-testcontainers?rev=a68333dc22a39574e951438f83c4679a6074f0ce#a68333dc22a39574e951438f83c4679a6074f0ce" dependencies = [ "anyhow", "gix", + "k256", "testcontainers", ] diff --git a/Cargo.toml b/Cargo.toml index d9b7e5a2..2ad02341 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,7 +92,7 @@ tonic = { version = "0.11.0", features = [ prost = { version = "0.12.4", optional = true } hmac = { version = "0.12.1", optional = true } testcontainers = { version = "0.20.0", optional = true } -yral-testcontainers = { git = "https://github.com/go-bazzinga/yral-testcontainers", rev = "14740097702fbc925ec2dbaa2b4a7660775576f4", optional = true } +yral-testcontainers = { git = "https://github.com/go-bazzinga/yral-testcontainers", rev = "a68333dc22a39574e951438f83c4679a6074f0ce", optional = true } [build-dependencies] serde = { version = "1.0", features = ["derive"] } @@ -171,6 +171,7 @@ local-bin = [ "ssr", "redis-kv", "local-auth", + "backend-admin", "dep:testcontainers", "dep:yral-testcontainers", ] @@ -178,6 +179,7 @@ local-lib = [ "hydrate", "redis-kv", "local-auth", + "backend-admin", ] [profile.wasm-release] diff --git a/local-run.sh b/local-run.sh index f8ec5a4e..a1834740 100755 --- a/local-run.sh +++ b/local-run.sh @@ -1,4 +1,4 @@ #!/bin/bash -cargo leptos build --bin-features local-bin --lib-features local-lib +cargo leptos build --bin-features local-bin --lib-features local-lib || exit 1 LEPTOS_SITE_ROOT="./target/site" LEPTOS_HASH_FILES=true ./target/debug/hot-or-not-web-leptos-ssr diff --git a/src/init/containers.rs b/src/init/containers.rs index 2f39ca21..31bf4943 100644 --- a/src/init/containers.rs +++ b/src/init/containers.rs @@ -1,13 +1,23 @@ +use std::time::Duration; + +use ic_agent::{identity::Secp256k1Identity, AgentError, Identity}; +use k256::SecretKey; use testcontainers::{ core::{ContainerPort, IntoContainerPort, WaitFor}, runners::AsyncRunner, ContainerAsync, GenericImage, Image, ImageExt, }; +use yral_metadata_client::MetadataClient; +use yral_metadata_types::UserMetadata; use yral_testcontainers::{ - backend::{self, YralBackend}, + backend::{self, YralBackend, ADMIN_SECP_BYTES}, metadata::{self, YralMetadata}, }; +use crate::{ + canister::USER_INDEX_ID, consts::METADATA_API_BASE, state::admin_canisters::AdminCanisters, +}; + type MaybeContainer = Option>; /// Holds all the containers that are started for local testing @@ -39,6 +49,39 @@ impl TestContainers { pub async fn start_metadata(&mut self) { self.metadata = Some(Self::start_image(YralMetadata, metadata::REST_PORT).await); + + // Setup User Principal -> User Canister ID + // for the admin canister + let metadata_client: MetadataClient = + MetadataClient::with_base_url(METADATA_API_BASE.clone()); + let sk = SecretKey::from_bytes(&ADMIN_SECP_BYTES.into()).unwrap(); + let id = Secp256k1Identity::from_private_key(sk); + let cans = AdminCanisters::new(id.clone()); + + let user_index = cans.user_index_with(USER_INDEX_ID).await.unwrap(); + let admin_principal = id.sender().unwrap(); + let admin_canister = loop { + let res = user_index + .get_user_canister_id_from_user_principal_id(admin_principal) + .await; + match res { + Ok(princ) => break princ.unwrap(), + Err(AgentError::HttpError(_)) => { + tokio::time::sleep(Duration::from_secs(8)).await; + continue; + } + Err(e) => panic!("Failed to get user canister {e}"), + } + }; + let metadata = UserMetadata { + user_canister_id: admin_canister, + user_name: "".into(), + }; + + metadata_client + .set_user_metadata(&id, metadata) + .await + .unwrap() } pub async fn start_backend(&mut self) { diff --git a/src/init/mod.rs b/src/init/mod.rs index f6e75dc8..b542db46 100644 --- a/src/init/mod.rs +++ b/src/init/mod.rs @@ -69,14 +69,29 @@ async fn init_grpc_offchain_channel() -> tonic::transport::Channel { #[cfg(feature = "backend-admin")] fn init_admin_canisters() -> crate::state::admin_canisters::AdminCanisters { use crate::state::admin_canisters::AdminCanisters; - use ic_agent::identity::BasicIdentity; - - let admin_id_pem = - env::var("BACKEND_ADMIN_IDENTITY").expect("`BACKEND_ADMIN_IDENTITY` is required!"); - let admin_id_pem_by = admin_id_pem.as_bytes(); - let admin_id = - BasicIdentity::from_pem(admin_id_pem_by).expect("Invalid `BACKEND_ADMIN_IDENTITY`"); - AdminCanisters::new(admin_id) + + #[cfg(feature = "local-bin")] + { + use ic_agent::identity::Secp256k1Identity; + use k256::SecretKey; + use yral_testcontainers::backend::ADMIN_SECP_BYTES; + + let sk = SecretKey::from_bytes(&ADMIN_SECP_BYTES.into()).unwrap(); + let identity = Secp256k1Identity::from_private_key(sk); + AdminCanisters::new(identity) + } + + #[cfg(not(feature = "local-bin"))] + { + use ic_agent::identity::BasicIdentity; + + let admin_id_pem = + env::var("BACKEND_ADMIN_IDENTITY").expect("`BACKEND_ADMIN_IDENTITY` is required!"); + let admin_id_pem_by = admin_id_pem.as_bytes(); + let admin_id = + BasicIdentity::from_pem(admin_id_pem_by).expect("Invalid `BACKEND_ADMIN_IDENTITY`"); + AdminCanisters::new(admin_id) + } } pub struct AppStateRes { From fd1fee3cee863aec4be8f87af9b05c1db180596d Mon Sep 17 00:00:00 2001 From: rupansh Date: Tue, 23 Jul 2024 23:41:07 +0530 Subject: [PATCH 6/8] chore: bump yral-testcontainers --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/init/containers.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d90abfb0..f0c37d3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6735,7 +6735,7 @@ dependencies = [ [[package]] name = "yral-testcontainers" version = "0.1.0" -source = "git+https://github.com/go-bazzinga/yral-testcontainers?rev=a68333dc22a39574e951438f83c4679a6074f0ce#a68333dc22a39574e951438f83c4679a6074f0ce" +source = "git+https://github.com/go-bazzinga/yral-testcontainers?rev=12c9e911a9420bd49576f4cf9db37c314e99a99a#12c9e911a9420bd49576f4cf9db37c314e99a99a" dependencies = [ "anyhow", "gix", diff --git a/Cargo.toml b/Cargo.toml index 2ad02341..39cef296 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,7 +92,7 @@ tonic = { version = "0.11.0", features = [ prost = { version = "0.12.4", optional = true } hmac = { version = "0.12.1", optional = true } testcontainers = { version = "0.20.0", optional = true } -yral-testcontainers = { git = "https://github.com/go-bazzinga/yral-testcontainers", rev = "a68333dc22a39574e951438f83c4679a6074f0ce", optional = true } +yral-testcontainers = { git = "https://github.com/go-bazzinga/yral-testcontainers", rev = "12c9e911a9420bd49576f4cf9db37c314e99a99a", optional = true } [build-dependencies] serde = { version = "1.0", features = ["derive"] } diff --git a/src/init/containers.rs b/src/init/containers.rs index 31bf4943..24e9e1d6 100644 --- a/src/init/containers.rs +++ b/src/init/containers.rs @@ -66,7 +66,7 @@ impl TestContainers { .await; match res { Ok(princ) => break princ.unwrap(), - Err(AgentError::HttpError(_)) => { + Err(AgentError::HttpError(_) | AgentError::CertificateOutdated(_)) => { tokio::time::sleep(Duration::from_secs(8)).await; continue; } From 817456840548e0946ff35366ce846eb6b8c74bdf Mon Sep 17 00:00:00 2001 From: rupansh Date: Wed, 24 Jul 2024 13:15:03 +0530 Subject: [PATCH 7/8] chore(README): add info about the local-run script --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 2deba931..20534c89 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,12 @@ Addtionally, Cargo.toml may need updating as new versions of the dependencies ar cargo leptos watch ``` +## Local Testing with testcontainers + +```bash +./local-run.sh +``` + ## Installing Additional Tools By default, `cargo-leptos` uses `nightly` Rust, `cargo-generate`, and `sass`. If you run into any trouble, you may need to install one or more of these tools. From cb7cc692677620ed386a9f5da0dd91d8c7fe9455 Mon Sep 17 00:00:00 2001 From: rupansh Date: Wed, 24 Jul 2024 13:28:28 +0530 Subject: [PATCH 8/8] chore: bump yral-testcontainers --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/consts/local.rs | 3 +++ src/init/containers.rs | 10 +++++++--- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f0c37d3f..57ac3109 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6735,7 +6735,7 @@ dependencies = [ [[package]] name = "yral-testcontainers" version = "0.1.0" -source = "git+https://github.com/go-bazzinga/yral-testcontainers?rev=12c9e911a9420bd49576f4cf9db37c314e99a99a#12c9e911a9420bd49576f4cf9db37c314e99a99a" +source = "git+https://github.com/go-bazzinga/yral-testcontainers?rev=f9d2c01c498d58fca0595a48bdc3f9400e57ec2f#f9d2c01c498d58fca0595a48bdc3f9400e57ec2f" dependencies = [ "anyhow", "gix", diff --git a/Cargo.toml b/Cargo.toml index 39cef296..26fae22f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,7 +92,7 @@ tonic = { version = "0.11.0", features = [ prost = { version = "0.12.4", optional = true } hmac = { version = "0.12.1", optional = true } testcontainers = { version = "0.20.0", optional = true } -yral-testcontainers = { git = "https://github.com/go-bazzinga/yral-testcontainers", rev = "12c9e911a9420bd49576f4cf9db37c314e99a99a", optional = true } +yral-testcontainers = { git = "https://github.com/go-bazzinga/yral-testcontainers", rev = "f9d2c01c498d58fca0595a48bdc3f9400e57ec2f", optional = true } [build-dependencies] serde = { version = "1.0", features = ["derive"] } diff --git a/src/consts/local.rs b/src/consts/local.rs index 66f17f8f..783f29c1 100644 --- a/src/consts/local.rs +++ b/src/consts/local.rs @@ -5,3 +5,6 @@ pub static METADATA_API_BASE: Lazy = Lazy::new(|| Url::parse("http://localhost:8001").unwrap()); pub const AGENT_URL: &str = "http://localhost:4943"; + +pub const YRAL_BACKEND_CONTAINER_TAG: &str = "76bfd0fa78e4f862a4b30601f4ff3143aa974ee7"; +pub const YRAL_METADATA_CONTAINER_TAG: &str = "a4879e2e711c17beeb12ed6987ba315c110be9e5"; diff --git a/src/init/containers.rs b/src/init/containers.rs index 24e9e1d6..6e524a90 100644 --- a/src/init/containers.rs +++ b/src/init/containers.rs @@ -15,7 +15,9 @@ use yral_testcontainers::{ }; use crate::{ - canister::USER_INDEX_ID, consts::METADATA_API_BASE, state::admin_canisters::AdminCanisters, + canister::USER_INDEX_ID, + consts::{METADATA_API_BASE, YRAL_BACKEND_CONTAINER_TAG, YRAL_METADATA_CONTAINER_TAG}, + state::admin_canisters::AdminCanisters, }; type MaybeContainer = Option>; @@ -48,7 +50,8 @@ impl TestContainers { } pub async fn start_metadata(&mut self) { - self.metadata = Some(Self::start_image(YralMetadata, metadata::REST_PORT).await); + let img = YralMetadata::new(YRAL_METADATA_CONTAINER_TAG.into()); + self.metadata = Some(Self::start_image(img, metadata::REST_PORT).await); // Setup User Principal -> User Canister ID // for the admin canister @@ -85,6 +88,7 @@ impl TestContainers { } pub async fn start_backend(&mut self) { - self.backend = Some(Self::start_image(YralBackend, backend::AGENT_PORT).await); + let img = YralBackend::new(YRAL_BACKEND_CONTAINER_TAG.into()); + self.backend = Some(Self::start_image(img, backend::AGENT_PORT).await); } }