Constellation, Spacedust, Slingshot, UFOs: atproto crates and services for microcosm

Merge pull request #16 from at-microcosm/constellation/filtering

Filter links by linker dids

authored by bad-example.com and committed by GitHub 6eb61e35 b0a66a10

Changed files
+790 -417
constellation
reflector
src
spacedust
who-am-i
src
+163 -133
Cargo.lock
··· 162 "proc-macro2", 163 "quote", 164 "serde", 165 - "syn 2.0.103", 166 ] 167 168 [[package]] ··· 204 dependencies = [ 205 "proc-macro2", 206 "quote", 207 - "syn 2.0.103", 208 "synstructure", 209 ] 210 ··· 216 dependencies = [ 217 "proc-macro2", 218 "quote", 219 - "syn 2.0.103", 220 ] 221 222 [[package]] ··· 274 dependencies = [ 275 "proc-macro2", 276 "quote", 277 - "syn 2.0.103", 278 ] 279 280 [[package]] ··· 291 dependencies = [ 292 "proc-macro2", 293 "quote", 294 - "syn 2.0.103", 295 ] 296 297 [[package]] ··· 507 "derive_utils", 508 "proc-macro2", 509 "quote", 510 - "syn 2.0.103", 511 ] 512 513 [[package]] ··· 603 "axum-core", 604 "bytes", 605 "cookie", 606 "futures-util", 607 "headers", 608 "http", ··· 612 "pin-project-lite", 613 "rustversion", 614 "serde", 615 "tower", 616 "tower-layer", 617 "tower-service", ··· 746 "regex", 747 "rustc-hash 1.1.0", 748 "shlex", 749 - "syn 2.0.103", 750 "which", 751 ] 752 ··· 765 "regex", 766 "rustc-hash 1.1.0", 767 "shlex", 768 - "syn 2.0.103", 769 ] 770 771 [[package]] ··· 783 "regex", 784 "rustc-hash 2.1.1", 785 "shlex", 786 - "syn 2.0.103", 787 ] 788 789 [[package]] ··· 859 860 [[package]] 861 name = "camino" 862 - version = "1.1.9" 863 source = "registry+https://github.com/rust-lang/crates.io-index" 864 - checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" 865 dependencies = [ 866 - "serde", 867 ] 868 869 [[package]] ··· 1018 "heck", 1019 "proc-macro2", 1020 "quote", 1021 - "syn 2.0.103", 1022 ] 1023 1024 [[package]] ··· 1310 "proc-macro2", 1311 "quote", 1312 "strsim 0.11.1", 1313 - "syn 2.0.103", 1314 ] 1315 1316 [[package]] ··· 1332 dependencies = [ 1333 "darling_core 0.20.11", 1334 "quote", 1335 - "syn 2.0.103", 1336 ] 1337 1338 [[package]] ··· 1372 checksum = "18e4fdb82bd54a12e42fb58a800dcae6b9e13982238ce2296dc3570b92148e1f" 1373 dependencies = [ 1374 "data-encoding", 1375 - "syn 2.0.103", 1376 ] 1377 1378 [[package]] ··· 1434 "darling 0.20.11", 1435 "proc-macro2", 1436 "quote", 1437 - "syn 2.0.103", 1438 ] 1439 1440 [[package]] ··· 1444 checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" 1445 dependencies = [ 1446 "derive_builder_core", 1447 - "syn 2.0.103", 1448 ] 1449 1450 [[package]] ··· 1464 dependencies = [ 1465 "proc-macro2", 1466 "quote", 1467 - "syn 2.0.103", 1468 "unicode-xid", 1469 ] 1470 ··· 1476 dependencies = [ 1477 "proc-macro2", 1478 "quote", 1479 - "syn 2.0.103", 1480 ] 1481 1482 [[package]] ··· 1520 dependencies = [ 1521 "proc-macro2", 1522 "quote", 1523 - "syn 2.0.103", 1524 ] 1525 1526 [[package]] ··· 1537 1538 [[package]] 1539 name = "dropshot" 1540 - version = "0.16.2" 1541 source = "registry+https://github.com/rust-lang/crates.io-index" 1542 - checksum = "50e8fed669e35e757646ad10f97c4d26dd22cce3da689b307954f7000d2719d0" 1543 dependencies = [ 1544 "async-stream", 1545 "async-trait", ··· 1556 "http-body-util", 1557 "hyper", 1558 "hyper-util", 1559 - "indexmap 2.9.0", 1560 "multer", 1561 "openapiv3", 1562 "paste", ··· 1579 "thiserror 2.0.16", 1580 "tokio", 1581 "tokio-rustls 0.25.0", 1582 - "toml", 1583 "uuid", 1584 "version_check", 1585 "waitgroup", ··· 1587 1588 [[package]] 1589 name = "dropshot_endpoint" 1590 - version = "0.16.2" 1591 source = "registry+https://github.com/rust-lang/crates.io-index" 1592 - checksum = "acebb687581abdeaa2c89fa448818a5f803b0e68e5d7e7a1cf585a8f3c5c57ac" 1593 dependencies = [ 1594 "heck", 1595 "proc-macro2", ··· 1597 "semver", 1598 "serde", 1599 "serde_tokenstream", 1600 - "syn 2.0.103", 1601 ] 1602 1603 [[package]] ··· 1670 "heck", 1671 "proc-macro2", 1672 "quote", 1673 - "syn 2.0.103", 1674 ] 1675 1676 [[package]] ··· 1682 "once_cell", 1683 "proc-macro2", 1684 "quote", 1685 - "syn 2.0.103", 1686 ] 1687 1688 [[package]] ··· 2062 dependencies = [ 2063 "proc-macro2", 2064 "quote", 2065 - "syn 2.0.103", 2066 ] 2067 2068 [[package]] ··· 2187 "futures-core", 2188 "futures-sink", 2189 "http", 2190 - "indexmap 2.9.0", 2191 "slab", 2192 "tokio", 2193 "tokio-util", ··· 2557 "js-sys", 2558 "log", 2559 "wasm-bindgen", 2560 - "windows-core 0.61.0", 2561 ] 2562 2563 [[package]] ··· 2684 dependencies = [ 2685 "proc-macro2", 2686 "quote", 2687 - "syn 2.0.103", 2688 ] 2689 2690 [[package]] ··· 2727 2728 [[package]] 2729 name = "indexmap" 2730 - version = "2.9.0" 2731 source = "registry+https://github.com/rust-lang/crates.io-index" 2732 - checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" 2733 dependencies = [ 2734 "equivalent", 2735 "hashbrown 0.15.2", 2736 "serde", 2737 ] 2738 2739 [[package]] ··· 2887 dependencies = [ 2888 "proc-macro2", 2889 "quote", 2890 - "syn 2.0.103", 2891 ] 2892 2893 [[package]] ··· 3041 checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" 3042 dependencies = [ 3043 "cfg-if", 3044 - "windows-targets 0.52.6", 3045 ] 3046 3047 [[package]] ··· 3264 "spin", 3265 "tokio", 3266 "tokio-util", 3267 - "toml", 3268 "tracing", 3269 "tracing-subscriber", 3270 ] ··· 3354 "http-body-util", 3355 "hyper", 3356 "hyper-util", 3357 - "indexmap 2.9.0", 3358 "ipnet", 3359 "metrics", 3360 "metrics-util 0.19.0", ··· 3375 "hyper", 3376 "hyper-rustls", 3377 "hyper-util", 3378 - "indexmap 2.9.0", 3379 "ipnet", 3380 "metrics", 3381 "metrics-util 0.20.0", ··· 3737 3738 [[package]] 3739 name = "openapiv3" 3740 - version = "2.0.0" 3741 source = "registry+https://github.com/rust-lang/crates.io-index" 3742 - checksum = "cc02deea53ffe807708244e5914f6b099ad7015a207ee24317c22112e17d9c5c" 3743 dependencies = [ 3744 - "indexmap 2.9.0", 3745 "serde", 3746 "serde_json", 3747 ] ··· 3769 dependencies = [ 3770 "proc-macro2", 3771 "quote", 3772 - "syn 2.0.103", 3773 ] 3774 3775 [[package]] ··· 3946 "pest_meta", 3947 "proc-macro2", 3948 "quote", 3949 - "syn 2.0.103", 3950 ] 3951 3952 [[package]] ··· 3976 dependencies = [ 3977 "proc-macro2", 3978 "quote", 3979 - "syn 2.0.103", 3980 ] 3981 3982 [[package]] ··· 4094 "proc-macro-crate", 4095 "proc-macro2", 4096 "quote", 4097 - "syn 2.0.103", 4098 ] 4099 4100 [[package]] ··· 4107 "bytes", 4108 "derive_more", 4109 "futures-util", 4110 - "indexmap 2.9.0", 4111 "itertools 0.14.0", 4112 "mime", 4113 "num-traits", ··· 4131 dependencies = [ 4132 "darling 0.20.11", 4133 "http", 4134 - "indexmap 2.9.0", 4135 "mime", 4136 "proc-macro-crate", 4137 "proc-macro2", 4138 "quote", 4139 "regex", 4140 - "syn 2.0.103", 4141 "thiserror 2.0.16", 4142 ] 4143 ··· 4178 checksum = "6837b9e10d61f45f987d50808f83d1ee3d206c66acf650c3e4ae2e1f6ddedf55" 4179 dependencies = [ 4180 "proc-macro2", 4181 - "syn 2.0.103", 4182 ] 4183 4184 [[package]] ··· 4489 dependencies = [ 4490 "proc-macro2", 4491 "quote", 4492 - "syn 2.0.103", 4493 ] 4494 4495 [[package]] ··· 4871 "proc-macro2", 4872 "quote", 4873 "serde_derive_internals", 4874 - "syn 2.0.103", 4875 ] 4876 4877 [[package]] ··· 4970 4971 [[package]] 4972 name = "serde" 4973 - version = "1.0.219" 4974 source = "registry+https://github.com/rust-lang/crates.io-index" 4975 - checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 4976 dependencies = [ 4977 "serde_derive", 4978 ] 4979 ··· 4987 ] 4988 4989 [[package]] 4990 name = "serde_derive" 4991 - version = "1.0.219" 4992 source = "registry+https://github.com/rust-lang/crates.io-index" 4993 - checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 4994 dependencies = [ 4995 "proc-macro2", 4996 "quote", 4997 - "syn 2.0.103", 4998 ] 4999 5000 [[package]] ··· 5005 dependencies = [ 5006 "proc-macro2", 5007 "quote", 5008 - "syn 2.0.103", 5009 ] 5010 5011 [[package]] ··· 5015 checksum = "9d2de91cf02bbc07cde38891769ccd5d4f073d22a40683aa4bc7a95781aaa2c4" 5016 dependencies = [ 5017 "form_urlencoded", 5018 - "indexmap 2.9.0", 5019 "itoa", 5020 "ryu", 5021 "serde", ··· 5023 5024 [[package]] 5025 name = "serde_json" 5026 - version = "1.0.141" 5027 source = "registry+https://github.com/rust-lang/crates.io-index" 5028 - checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" 5029 dependencies = [ 5030 "itoa", 5031 "memchr", 5032 "ryu", 5033 "serde", 5034 ] 5035 5036 [[package]] ··· 5066 ] 5067 5068 [[package]] 5069 name = "serde_tokenstream" 5070 version = "0.2.2" 5071 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5074 "proc-macro2", 5075 "quote", 5076 "serde", 5077 - "syn 2.0.103", 5078 ] 5079 5080 [[package]] ··· 5099 "chrono", 5100 "hex", 5101 "indexmap 1.9.3", 5102 - "indexmap 2.9.0", 5103 "serde", 5104 "serde_derive", 5105 "serde_json", ··· 5116 "darling 0.20.11", 5117 "proc-macro2", 5118 "quote", 5119 - "syn 2.0.103", 5120 ] 5121 5122 [[package]] ··· 5125 source = "registry+https://github.com/rust-lang/crates.io-index" 5126 checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" 5127 dependencies = [ 5128 - "indexmap 2.9.0", 5129 "itoa", 5130 "ryu", 5131 "serde", ··· 5418 5419 [[package]] 5420 name = "syn" 5421 - version = "2.0.103" 5422 source = "registry+https://github.com/rust-lang/crates.io-index" 5423 - checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" 5424 dependencies = [ 5425 "proc-macro2", 5426 "quote", ··· 5444 dependencies = [ 5445 "proc-macro2", 5446 "quote", 5447 - "syn 2.0.103", 5448 ] 5449 5450 [[package]] ··· 5530 dependencies = [ 5531 "proc-macro2", 5532 "quote", 5533 - "syn 2.0.103", 5534 ] 5535 5536 [[package]] ··· 5541 dependencies = [ 5542 "proc-macro2", 5543 "quote", 5544 - "syn 2.0.103", 5545 ] 5546 5547 [[package]] ··· 5666 dependencies = [ 5667 "proc-macro2", 5668 "quote", 5669 - "syn 2.0.103", 5670 ] 5671 5672 [[package]] ··· 5757 checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" 5758 dependencies = [ 5759 "serde", 5760 - "serde_spanned", 5761 - "toml_datetime", 5762 "toml_edit", 5763 ] 5764 5765 [[package]] 5766 name = "toml_datetime" 5767 version = "0.6.11" 5768 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5772 ] 5773 5774 [[package]] 5775 name = "toml_edit" 5776 version = "0.22.27" 5777 source = "registry+https://github.com/rust-lang/crates.io-index" 5778 checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" 5779 dependencies = [ 5780 - "indexmap 2.9.0", 5781 "serde", 5782 - "serde_spanned", 5783 - "toml_datetime", 5784 "toml_write", 5785 "winnow", 5786 ] 5787 5788 [[package]] 5789 name = "toml_write" 5790 version = "0.1.2" 5791 source = "registry+https://github.com/rust-lang/crates.io-index" 5792 checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" 5793 5794 [[package]] 5795 name = "tower" 5796 version = "0.5.2" 5797 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5857 dependencies = [ 5858 "proc-macro2", 5859 "quote", 5860 - "syn 2.0.103", 5861 ] 5862 5863 [[package]] ··· 5907 dependencies = [ 5908 "proc-macro2", 5909 "quote", 5910 - "syn 2.0.103", 5911 ] 5912 5913 [[package]] ··· 6107 6108 [[package]] 6109 name = "uuid" 6110 - version = "1.16.0" 6111 source = "registry+https://github.com/rust-lang/crates.io-index" 6112 - checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" 6113 dependencies = [ 6114 "getrandom 0.3.3", 6115 "serde", 6116 ] 6117 6118 [[package]] ··· 6227 "log", 6228 "proc-macro2", 6229 "quote", 6230 - "syn 2.0.103", 6231 "wasm-bindgen-shared", 6232 ] 6233 ··· 6262 dependencies = [ 6263 "proc-macro2", 6264 "quote", 6265 - "syn 2.0.103", 6266 "wasm-bindgen-backend", 6267 "wasm-bindgen-shared", 6268 ] ··· 6375 source = "registry+https://github.com/rust-lang/crates.io-index" 6376 checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 6377 dependencies = [ 6378 - "windows-sys 0.59.0", 6379 ] 6380 6381 [[package]] ··· 6390 source = "registry+https://github.com/rust-lang/crates.io-index" 6391 checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" 6392 dependencies = [ 6393 - "windows-core 0.58.0", 6394 "windows-targets 0.52.6", 6395 ] 6396 ··· 6400 source = "registry+https://github.com/rust-lang/crates.io-index" 6401 checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" 6402 dependencies = [ 6403 - "windows-implement 0.58.0", 6404 - "windows-interface 0.58.0", 6405 "windows-result 0.2.0", 6406 "windows-strings 0.1.0", 6407 "windows-targets 0.52.6", 6408 ] 6409 6410 [[package]] 6411 - name = "windows-core" 6412 - version = "0.61.0" 6413 - source = "registry+https://github.com/rust-lang/crates.io-index" 6414 - checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" 6415 - dependencies = [ 6416 - "windows-implement 0.60.0", 6417 - "windows-interface 0.59.1", 6418 - "windows-link", 6419 - "windows-result 0.3.4", 6420 - "windows-strings 0.4.2", 6421 - ] 6422 - 6423 - [[package]] 6424 name = "windows-implement" 6425 version = "0.58.0" 6426 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6428 dependencies = [ 6429 "proc-macro2", 6430 "quote", 6431 - "syn 2.0.103", 6432 - ] 6433 - 6434 - [[package]] 6435 - name = "windows-implement" 6436 - version = "0.60.0" 6437 - source = "registry+https://github.com/rust-lang/crates.io-index" 6438 - checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" 6439 - dependencies = [ 6440 - "proc-macro2", 6441 - "quote", 6442 - "syn 2.0.103", 6443 ] 6444 6445 [[package]] ··· 6450 dependencies = [ 6451 "proc-macro2", 6452 "quote", 6453 - "syn 2.0.103", 6454 - ] 6455 - 6456 - [[package]] 6457 - name = "windows-interface" 6458 - version = "0.59.1" 6459 - source = "registry+https://github.com/rust-lang/crates.io-index" 6460 - checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" 6461 - dependencies = [ 6462 - "proc-macro2", 6463 - "quote", 6464 - "syn 2.0.103", 6465 ] 6466 6467 [[package]] ··· 6668 6669 [[package]] 6670 name = "winnow" 6671 - version = "0.7.11" 6672 source = "registry+https://github.com/rust-lang/crates.io-index" 6673 - checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" 6674 dependencies = [ 6675 "memchr", 6676 ] ··· 6767 dependencies = [ 6768 "proc-macro2", 6769 "quote", 6770 - "syn 2.0.103", 6771 "synstructure", 6772 ] 6773 ··· 6797 dependencies = [ 6798 "proc-macro2", 6799 "quote", 6800 - "syn 2.0.103", 6801 ] 6802 6803 [[package]] ··· 6808 dependencies = [ 6809 "proc-macro2", 6810 "quote", 6811 - "syn 2.0.103", 6812 ] 6813 6814 [[package]] ··· 6828 dependencies = [ 6829 "proc-macro2", 6830 "quote", 6831 - "syn 2.0.103", 6832 "synstructure", 6833 ] 6834 ··· 6850 dependencies = [ 6851 "proc-macro2", 6852 "quote", 6853 - "syn 2.0.103", 6854 ] 6855 6856 [[package]] ··· 6872 dependencies = [ 6873 "proc-macro2", 6874 "quote", 6875 - "syn 2.0.103", 6876 ] 6877 6878 [[package]]
··· 162 "proc-macro2", 163 "quote", 164 "serde", 165 + "syn 2.0.106", 166 ] 167 168 [[package]] ··· 204 dependencies = [ 205 "proc-macro2", 206 "quote", 207 + "syn 2.0.106", 208 "synstructure", 209 ] 210 ··· 216 dependencies = [ 217 "proc-macro2", 218 "quote", 219 + "syn 2.0.106", 220 ] 221 222 [[package]] ··· 274 dependencies = [ 275 "proc-macro2", 276 "quote", 277 + "syn 2.0.106", 278 ] 279 280 [[package]] ··· 291 dependencies = [ 292 "proc-macro2", 293 "quote", 294 + "syn 2.0.106", 295 ] 296 297 [[package]] ··· 507 "derive_utils", 508 "proc-macro2", 509 "quote", 510 + "syn 2.0.106", 511 ] 512 513 [[package]] ··· 603 "axum-core", 604 "bytes", 605 "cookie", 606 + "form_urlencoded", 607 "futures-util", 608 "headers", 609 "http", ··· 613 "pin-project-lite", 614 "rustversion", 615 "serde", 616 + "serde_html_form", 617 + "serde_path_to_error", 618 "tower", 619 "tower-layer", 620 "tower-service", ··· 749 "regex", 750 "rustc-hash 1.1.0", 751 "shlex", 752 + "syn 2.0.106", 753 "which", 754 ] 755 ··· 768 "regex", 769 "rustc-hash 1.1.0", 770 "shlex", 771 + "syn 2.0.106", 772 ] 773 774 [[package]] ··· 786 "regex", 787 "rustc-hash 2.1.1", 788 "shlex", 789 + "syn 2.0.106", 790 ] 791 792 [[package]] ··· 862 863 [[package]] 864 name = "camino" 865 + version = "1.2.1" 866 source = "registry+https://github.com/rust-lang/crates.io-index" 867 + checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" 868 dependencies = [ 869 + "serde_core", 870 ] 871 872 [[package]] ··· 1021 "heck", 1022 "proc-macro2", 1023 "quote", 1024 + "syn 2.0.106", 1025 ] 1026 1027 [[package]] ··· 1313 "proc-macro2", 1314 "quote", 1315 "strsim 0.11.1", 1316 + "syn 2.0.106", 1317 ] 1318 1319 [[package]] ··· 1335 dependencies = [ 1336 "darling_core 0.20.11", 1337 "quote", 1338 + "syn 2.0.106", 1339 ] 1340 1341 [[package]] ··· 1375 checksum = "18e4fdb82bd54a12e42fb58a800dcae6b9e13982238ce2296dc3570b92148e1f" 1376 dependencies = [ 1377 "data-encoding", 1378 + "syn 1.0.109", 1379 ] 1380 1381 [[package]] ··· 1437 "darling 0.20.11", 1438 "proc-macro2", 1439 "quote", 1440 + "syn 2.0.106", 1441 ] 1442 1443 [[package]] ··· 1447 checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" 1448 dependencies = [ 1449 "derive_builder_core", 1450 + "syn 2.0.106", 1451 ] 1452 1453 [[package]] ··· 1467 dependencies = [ 1468 "proc-macro2", 1469 "quote", 1470 + "syn 2.0.106", 1471 "unicode-xid", 1472 ] 1473 ··· 1479 dependencies = [ 1480 "proc-macro2", 1481 "quote", 1482 + "syn 2.0.106", 1483 ] 1484 1485 [[package]] ··· 1523 dependencies = [ 1524 "proc-macro2", 1525 "quote", 1526 + "syn 2.0.106", 1527 ] 1528 1529 [[package]] ··· 1540 1541 [[package]] 1542 name = "dropshot" 1543 + version = "0.16.3" 1544 source = "registry+https://github.com/rust-lang/crates.io-index" 1545 + checksum = "eedf902e40c1024b8ed9ca16378a54e9655cdf0e698245ba82d81a3778dcbc54" 1546 dependencies = [ 1547 "async-stream", 1548 "async-trait", ··· 1559 "http-body-util", 1560 "hyper", 1561 "hyper-util", 1562 + "indexmap 2.11.4", 1563 "multer", 1564 "openapiv3", 1565 "paste", ··· 1582 "thiserror 2.0.16", 1583 "tokio", 1584 "tokio-rustls 0.25.0", 1585 + "toml 0.9.7", 1586 "uuid", 1587 "version_check", 1588 "waitgroup", ··· 1590 1591 [[package]] 1592 name = "dropshot_endpoint" 1593 + version = "0.16.4" 1594 source = "registry+https://github.com/rust-lang/crates.io-index" 1595 + checksum = "89d09440e73a9dcf8a0f7fbd6ab889a7751d59f0fe76e5082a0a6d5623ec6da3" 1596 dependencies = [ 1597 "heck", 1598 "proc-macro2", ··· 1600 "semver", 1601 "serde", 1602 "serde_tokenstream", 1603 + "syn 2.0.106", 1604 ] 1605 1606 [[package]] ··· 1673 "heck", 1674 "proc-macro2", 1675 "quote", 1676 + "syn 2.0.106", 1677 ] 1678 1679 [[package]] ··· 1685 "once_cell", 1686 "proc-macro2", 1687 "quote", 1688 + "syn 2.0.106", 1689 ] 1690 1691 [[package]] ··· 2065 dependencies = [ 2066 "proc-macro2", 2067 "quote", 2068 + "syn 2.0.106", 2069 ] 2070 2071 [[package]] ··· 2190 "futures-core", 2191 "futures-sink", 2192 "http", 2193 + "indexmap 2.11.4", 2194 "slab", 2195 "tokio", 2196 "tokio-util", ··· 2560 "js-sys", 2561 "log", 2562 "wasm-bindgen", 2563 + "windows-core", 2564 ] 2565 2566 [[package]] ··· 2687 dependencies = [ 2688 "proc-macro2", 2689 "quote", 2690 + "syn 2.0.106", 2691 ] 2692 2693 [[package]] ··· 2730 2731 [[package]] 2732 name = "indexmap" 2733 + version = "2.11.4" 2734 source = "registry+https://github.com/rust-lang/crates.io-index" 2735 + checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" 2736 dependencies = [ 2737 "equivalent", 2738 "hashbrown 0.15.2", 2739 "serde", 2740 + "serde_core", 2741 ] 2742 2743 [[package]] ··· 2891 dependencies = [ 2892 "proc-macro2", 2893 "quote", 2894 + "syn 2.0.106", 2895 ] 2896 2897 [[package]] ··· 3045 checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" 3046 dependencies = [ 3047 "cfg-if", 3048 + "windows-targets 0.48.5", 3049 ] 3050 3051 [[package]] ··· 3268 "spin", 3269 "tokio", 3270 "tokio-util", 3271 + "toml 0.8.23", 3272 "tracing", 3273 "tracing-subscriber", 3274 ] ··· 3358 "http-body-util", 3359 "hyper", 3360 "hyper-util", 3361 + "indexmap 2.11.4", 3362 "ipnet", 3363 "metrics", 3364 "metrics-util 0.19.0", ··· 3379 "hyper", 3380 "hyper-rustls", 3381 "hyper-util", 3382 + "indexmap 2.11.4", 3383 "ipnet", 3384 "metrics", 3385 "metrics-util 0.20.0", ··· 3741 3742 [[package]] 3743 name = "openapiv3" 3744 + version = "2.2.0" 3745 source = "registry+https://github.com/rust-lang/crates.io-index" 3746 + checksum = "5c8d427828b22ae1fff2833a03d8486c2c881367f1c336349f307f321e7f4d05" 3747 dependencies = [ 3748 + "indexmap 2.11.4", 3749 "serde", 3750 "serde_json", 3751 ] ··· 3773 dependencies = [ 3774 "proc-macro2", 3775 "quote", 3776 + "syn 2.0.106", 3777 ] 3778 3779 [[package]] ··· 3950 "pest_meta", 3951 "proc-macro2", 3952 "quote", 3953 + "syn 2.0.106", 3954 ] 3955 3956 [[package]] ··· 3980 dependencies = [ 3981 "proc-macro2", 3982 "quote", 3983 + "syn 2.0.106", 3984 ] 3985 3986 [[package]] ··· 4098 "proc-macro-crate", 4099 "proc-macro2", 4100 "quote", 4101 + "syn 2.0.106", 4102 ] 4103 4104 [[package]] ··· 4111 "bytes", 4112 "derive_more", 4113 "futures-util", 4114 + "indexmap 2.11.4", 4115 "itertools 0.14.0", 4116 "mime", 4117 "num-traits", ··· 4135 dependencies = [ 4136 "darling 0.20.11", 4137 "http", 4138 + "indexmap 2.11.4", 4139 "mime", 4140 "proc-macro-crate", 4141 "proc-macro2", 4142 "quote", 4143 "regex", 4144 + "syn 2.0.106", 4145 "thiserror 2.0.16", 4146 ] 4147 ··· 4182 checksum = "6837b9e10d61f45f987d50808f83d1ee3d206c66acf650c3e4ae2e1f6ddedf55" 4183 dependencies = [ 4184 "proc-macro2", 4185 + "syn 2.0.106", 4186 ] 4187 4188 [[package]] ··· 4493 dependencies = [ 4494 "proc-macro2", 4495 "quote", 4496 + "syn 2.0.106", 4497 ] 4498 4499 [[package]] ··· 4875 "proc-macro2", 4876 "quote", 4877 "serde_derive_internals", 4878 + "syn 2.0.106", 4879 ] 4880 4881 [[package]] ··· 4974 4975 [[package]] 4976 name = "serde" 4977 + version = "1.0.228" 4978 source = "registry+https://github.com/rust-lang/crates.io-index" 4979 + checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" 4980 dependencies = [ 4981 + "serde_core", 4982 "serde_derive", 4983 ] 4984 ··· 4992 ] 4993 4994 [[package]] 4995 + name = "serde_core" 4996 + version = "1.0.228" 4997 + source = "registry+https://github.com/rust-lang/crates.io-index" 4998 + checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" 4999 + dependencies = [ 5000 + "serde_derive", 5001 + ] 5002 + 5003 + [[package]] 5004 name = "serde_derive" 5005 + version = "1.0.228" 5006 source = "registry+https://github.com/rust-lang/crates.io-index" 5007 + checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" 5008 dependencies = [ 5009 "proc-macro2", 5010 "quote", 5011 + "syn 2.0.106", 5012 ] 5013 5014 [[package]] ··· 5019 dependencies = [ 5020 "proc-macro2", 5021 "quote", 5022 + "syn 2.0.106", 5023 ] 5024 5025 [[package]] ··· 5029 checksum = "9d2de91cf02bbc07cde38891769ccd5d4f073d22a40683aa4bc7a95781aaa2c4" 5030 dependencies = [ 5031 "form_urlencoded", 5032 + "indexmap 2.11.4", 5033 "itoa", 5034 "ryu", 5035 "serde", ··· 5037 5038 [[package]] 5039 name = "serde_json" 5040 + version = "1.0.145" 5041 source = "registry+https://github.com/rust-lang/crates.io-index" 5042 + checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" 5043 dependencies = [ 5044 "itoa", 5045 "memchr", 5046 "ryu", 5047 "serde", 5048 + "serde_core", 5049 ] 5050 5051 [[package]] ··· 5081 ] 5082 5083 [[package]] 5084 + name = "serde_spanned" 5085 + version = "1.0.2" 5086 + source = "registry+https://github.com/rust-lang/crates.io-index" 5087 + checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee" 5088 + dependencies = [ 5089 + "serde_core", 5090 + ] 5091 + 5092 + [[package]] 5093 name = "serde_tokenstream" 5094 version = "0.2.2" 5095 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5098 "proc-macro2", 5099 "quote", 5100 "serde", 5101 + "syn 2.0.106", 5102 ] 5103 5104 [[package]] ··· 5123 "chrono", 5124 "hex", 5125 "indexmap 1.9.3", 5126 + "indexmap 2.11.4", 5127 "serde", 5128 "serde_derive", 5129 "serde_json", ··· 5140 "darling 0.20.11", 5141 "proc-macro2", 5142 "quote", 5143 + "syn 2.0.106", 5144 ] 5145 5146 [[package]] ··· 5149 source = "registry+https://github.com/rust-lang/crates.io-index" 5150 checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" 5151 dependencies = [ 5152 + "indexmap 2.11.4", 5153 "itoa", 5154 "ryu", 5155 "serde", ··· 5442 5443 [[package]] 5444 name = "syn" 5445 + version = "2.0.106" 5446 source = "registry+https://github.com/rust-lang/crates.io-index" 5447 + checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" 5448 dependencies = [ 5449 "proc-macro2", 5450 "quote", ··· 5468 dependencies = [ 5469 "proc-macro2", 5470 "quote", 5471 + "syn 2.0.106", 5472 ] 5473 5474 [[package]] ··· 5554 dependencies = [ 5555 "proc-macro2", 5556 "quote", 5557 + "syn 2.0.106", 5558 ] 5559 5560 [[package]] ··· 5565 dependencies = [ 5566 "proc-macro2", 5567 "quote", 5568 + "syn 2.0.106", 5569 ] 5570 5571 [[package]] ··· 5690 dependencies = [ 5691 "proc-macro2", 5692 "quote", 5693 + "syn 2.0.106", 5694 ] 5695 5696 [[package]] ··· 5781 checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" 5782 dependencies = [ 5783 "serde", 5784 + "serde_spanned 0.6.9", 5785 + "toml_datetime 0.6.11", 5786 "toml_edit", 5787 ] 5788 5789 [[package]] 5790 + name = "toml" 5791 + version = "0.9.7" 5792 + source = "registry+https://github.com/rust-lang/crates.io-index" 5793 + checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0" 5794 + dependencies = [ 5795 + "indexmap 2.11.4", 5796 + "serde_core", 5797 + "serde_spanned 1.0.2", 5798 + "toml_datetime 0.7.2", 5799 + "toml_parser", 5800 + "toml_writer", 5801 + "winnow", 5802 + ] 5803 + 5804 + [[package]] 5805 name = "toml_datetime" 5806 version = "0.6.11" 5807 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5811 ] 5812 5813 [[package]] 5814 + name = "toml_datetime" 5815 + version = "0.7.2" 5816 + source = "registry+https://github.com/rust-lang/crates.io-index" 5817 + checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1" 5818 + dependencies = [ 5819 + "serde_core", 5820 + ] 5821 + 5822 + [[package]] 5823 name = "toml_edit" 5824 version = "0.22.27" 5825 source = "registry+https://github.com/rust-lang/crates.io-index" 5826 checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" 5827 dependencies = [ 5828 + "indexmap 2.11.4", 5829 "serde", 5830 + "serde_spanned 0.6.9", 5831 + "toml_datetime 0.6.11", 5832 "toml_write", 5833 "winnow", 5834 ] 5835 5836 [[package]] 5837 + name = "toml_parser" 5838 + version = "1.0.3" 5839 + source = "registry+https://github.com/rust-lang/crates.io-index" 5840 + checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627" 5841 + dependencies = [ 5842 + "winnow", 5843 + ] 5844 + 5845 + [[package]] 5846 name = "toml_write" 5847 version = "0.1.2" 5848 source = "registry+https://github.com/rust-lang/crates.io-index" 5849 checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" 5850 5851 [[package]] 5852 + name = "toml_writer" 5853 + version = "1.0.3" 5854 + source = "registry+https://github.com/rust-lang/crates.io-index" 5855 + checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109" 5856 + 5857 + [[package]] 5858 name = "tower" 5859 version = "0.5.2" 5860 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5920 dependencies = [ 5921 "proc-macro2", 5922 "quote", 5923 + "syn 2.0.106", 5924 ] 5925 5926 [[package]] ··· 5970 dependencies = [ 5971 "proc-macro2", 5972 "quote", 5973 + "syn 2.0.106", 5974 ] 5975 5976 [[package]] ··· 6170 6171 [[package]] 6172 name = "uuid" 6173 + version = "1.18.1" 6174 source = "registry+https://github.com/rust-lang/crates.io-index" 6175 + checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" 6176 dependencies = [ 6177 "getrandom 0.3.3", 6178 + "js-sys", 6179 "serde", 6180 + "wasm-bindgen", 6181 ] 6182 6183 [[package]] ··· 6292 "log", 6293 "proc-macro2", 6294 "quote", 6295 + "syn 2.0.106", 6296 "wasm-bindgen-shared", 6297 ] 6298 ··· 6327 dependencies = [ 6328 "proc-macro2", 6329 "quote", 6330 + "syn 2.0.106", 6331 "wasm-bindgen-backend", 6332 "wasm-bindgen-shared", 6333 ] ··· 6440 source = "registry+https://github.com/rust-lang/crates.io-index" 6441 checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 6442 dependencies = [ 6443 + "windows-sys 0.48.0", 6444 ] 6445 6446 [[package]] ··· 6455 source = "registry+https://github.com/rust-lang/crates.io-index" 6456 checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" 6457 dependencies = [ 6458 + "windows-core", 6459 "windows-targets 0.52.6", 6460 ] 6461 ··· 6465 source = "registry+https://github.com/rust-lang/crates.io-index" 6466 checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" 6467 dependencies = [ 6468 + "windows-implement", 6469 + "windows-interface", 6470 "windows-result 0.2.0", 6471 "windows-strings 0.1.0", 6472 "windows-targets 0.52.6", 6473 ] 6474 6475 [[package]] 6476 name = "windows-implement" 6477 version = "0.58.0" 6478 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6480 dependencies = [ 6481 "proc-macro2", 6482 "quote", 6483 + "syn 2.0.106", 6484 ] 6485 6486 [[package]] ··· 6491 dependencies = [ 6492 "proc-macro2", 6493 "quote", 6494 + "syn 2.0.106", 6495 ] 6496 6497 [[package]] ··· 6698 6699 [[package]] 6700 name = "winnow" 6701 + version = "0.7.13" 6702 source = "registry+https://github.com/rust-lang/crates.io-index" 6703 + checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" 6704 dependencies = [ 6705 "memchr", 6706 ] ··· 6797 dependencies = [ 6798 "proc-macro2", 6799 "quote", 6800 + "syn 2.0.106", 6801 "synstructure", 6802 ] 6803 ··· 6827 dependencies = [ 6828 "proc-macro2", 6829 "quote", 6830 + "syn 2.0.106", 6831 ] 6832 6833 [[package]] ··· 6838 dependencies = [ 6839 "proc-macro2", 6840 "quote", 6841 + "syn 2.0.106", 6842 ] 6843 6844 [[package]] ··· 6858 dependencies = [ 6859 "proc-macro2", 6860 "quote", 6861 + "syn 2.0.106", 6862 "synstructure", 6863 ] 6864 ··· 6880 dependencies = [ 6881 "proc-macro2", 6882 "quote", 6883 + "syn 2.0.106", 6884 ] 6885 6886 [[package]] ··· 6902 dependencies = [ 6903 "proc-macro2", 6904 "quote", 6905 + "syn 2.0.106", 6906 ] 6907 6908 [[package]]
+1 -1
constellation/Cargo.toml
··· 8 anyhow = "1.0.95" 9 askama = { version = "0.12.1", features = ["serde-json"] } 10 axum = "0.8.1" 11 - axum-extra = { version = "0.10.0", features = ["typed-header"] } 12 axum-metrics = "0.2" 13 bincode = "1.3.3" 14 clap = { version = "4.5.26", features = ["derive"] }
··· 8 anyhow = "1.0.95" 9 askama = { version = "0.12.1", features = ["serde-json"] } 10 axum = "0.8.1" 11 + axum-extra = { version = "0.10.0", features = ["query", "typed-header"] } 12 axum-metrics = "0.2" 13 bincode = "1.3.3" 14 clap = { version = "4.5.26", features = ["derive"] }
+2
constellation/src/bin/rocks-restore-from-backup.rs
··· 3 use clap::Parser; 4 use std::path::PathBuf; 5 6 use rocksdb::backup::{BackupEngine, BackupEngineOptions, RestoreOptions}; 7 8 use std::time; ··· 19 to_data_dir: PathBuf, 20 } 21 22 fn main() -> Result<()> { 23 let args = Args::parse(); 24
··· 3 use clap::Parser; 4 use std::path::PathBuf; 5 6 + #[cfg(feature = "rocks")] 7 use rocksdb::backup::{BackupEngine, BackupEngineOptions, RestoreOptions}; 8 9 use std::time; ··· 20 to_data_dir: PathBuf, 21 } 22 23 + #[cfg(feature = "rocks")] 24 fn main() -> Result<()> { 25 let args = Args::parse(); 26
+47 -5
constellation/src/server/mod.rs
··· 11 use bincode::Options; 12 use serde::{Deserialize, Serialize}; 13 use serde_with::serde_as; 14 - use std::collections::HashMap; 15 use std::time::{Duration, UNIX_EPOCH}; 16 use tokio::net::{TcpListener, ToSocketAddrs}; 17 use tokio::task::block_in_place; ··· 238 collection: String, 239 path: String, 240 cursor: Option<OpaqueApiCursor>, 241 - limit: Option<u64>, 242 // TODO: allow reverse (er, forward) order as well 243 } 244 #[derive(Template, Serialize)] 245 #[template(path = "links.html.j2")] ··· 255 } 256 fn get_links( 257 accept: ExtractAccept, 258 - query: Query<GetLinkItemsQuery>, 259 store: impl LinkReader, 260 ) -> Result<impl IntoResponse, http::StatusCode> { 261 let until = query ··· 265 .transpose()? 266 .map(|c| c.next); 267 268 - let limit = query.limit.unwrap_or(DEFAULT_CURSOR_LIMIT); 269 if limit > DEFAULT_CURSOR_LIMIT_MAX { 270 return Err(http::StatusCode::BAD_REQUEST); 271 } 272 273 let paged = store 274 - .get_links(&query.target, &query.collection, &query.path, limit, until) 275 .map_err(|_| http::StatusCode::INTERNAL_SERVER_ERROR)?; 276 277 let cursor = paged.next.map(|next| {
··· 11 use bincode::Options; 12 use serde::{Deserialize, Serialize}; 13 use serde_with::serde_as; 14 + use std::collections::{HashMap, HashSet}; 15 use std::time::{Duration, UNIX_EPOCH}; 16 use tokio::net::{TcpListener, ToSocketAddrs}; 17 use tokio::task::block_in_place; ··· 238 collection: String, 239 path: String, 240 cursor: Option<OpaqueApiCursor>, 241 + /// Filter links only from these DIDs 242 + /// 243 + /// include multiple times to filter by multiple source DIDs 244 + #[serde(default)] 245 + did: Vec<String>, 246 + /// [deprecated] Filter links only from these DIDs 247 + /// 248 + /// format: comma-separated sequence of DIDs 249 + /// 250 + /// errors: if `did` parameter is also present 251 + /// 252 + /// deprecated: use `did`, which can be repeated multiple times 253 + from_dids: Option<String>, // comma separated: gross 254 + #[serde(default = "get_default_limit")] 255 + limit: u64, 256 // TODO: allow reverse (er, forward) order as well 257 + } 258 + fn get_default_limit() -> u64 { 259 + DEFAULT_CURSOR_LIMIT 260 } 261 #[derive(Template, Serialize)] 262 #[template(path = "links.html.j2")] ··· 272 } 273 fn get_links( 274 accept: ExtractAccept, 275 + query: axum_extra::extract::Query<GetLinkItemsQuery>, // supports multiple param occurrences 276 store: impl LinkReader, 277 ) -> Result<impl IntoResponse, http::StatusCode> { 278 let until = query ··· 282 .transpose()? 283 .map(|c| c.next); 284 285 + let limit = query.limit; 286 if limit > DEFAULT_CURSOR_LIMIT_MAX { 287 return Err(http::StatusCode::BAD_REQUEST); 288 } 289 290 + let mut filter_dids: HashSet<Did> = HashSet::from_iter( 291 + query 292 + .did 293 + .iter() 294 + .map(|d| d.trim()) 295 + .filter(|d| !d.is_empty()) 296 + .map(|d| Did(d.to_string())), 297 + ); 298 + 299 + if let Some(comma_joined) = &query.from_dids { 300 + if !filter_dids.is_empty() { 301 + return Err(http::StatusCode::BAD_REQUEST); 302 + } 303 + for did in comma_joined.split(',') { 304 + filter_dids.insert(Did(did.to_string())); 305 + } 306 + } 307 + 308 let paged = store 309 + .get_links( 310 + &query.target, 311 + &query.collection, 312 + &query.path, 313 + limit, 314 + until, 315 + &filter_dids, 316 + ) 317 .map_err(|_| http::StatusCode::INTERNAL_SERVER_ERROR)?; 318 319 let cursor = paged.next.map(|next| {
+15
constellation/src/storage/mem_store.rs
··· 166 path: &str, 167 limit: u64, 168 until: Option<u64>, 169 ) -> Result<PagedAppendingCollection<RecordId>> { 170 let data = self.0.lock().unwrap(); 171 let Some(paths) = data.targets.get(&Target::new(target)) else { ··· 183 next: None, 184 total: 0, 185 }); 186 }; 187 188 let total = did_rkeys.len();
··· 166 path: &str, 167 limit: u64, 168 until: Option<u64>, 169 + filter_dids: &HashSet<Did>, 170 ) -> Result<PagedAppendingCollection<RecordId>> { 171 let data = self.0.lock().unwrap(); 172 let Some(paths) = data.targets.get(&Target::new(target)) else { ··· 184 next: None, 185 total: 0, 186 }); 187 + }; 188 + 189 + let did_rkeys: Vec<_> = if !filter_dids.is_empty() { 190 + did_rkeys 191 + .iter() 192 + .filter(|m| { 193 + Option::<(Did, RKey)>::clone(m) 194 + .map(|(did, _)| filter_dids.contains(&did)) 195 + .unwrap_or(false) 196 + }) 197 + .cloned() 198 + .collect() 199 + } else { 200 + did_rkeys.to_vec() 201 }; 202 203 let total = did_rkeys.len();
+259 -14
constellation/src/storage/mod.rs
··· 1 use crate::{ActionableEvent, CountsByCount, Did, RecordId}; 2 use anyhow::Result; 3 use serde::{Deserialize, Serialize}; 4 - use std::collections::HashMap; 5 6 pub mod mem_store; 7 pub use mem_store::MemStorage; ··· 59 path: &str, 60 limit: u64, 61 until: Option<u64>, 62 ) -> Result<PagedAppendingCollection<RecordId>>; 63 64 fn get_distinct_dids( ··· 145 ); 146 assert_eq!(storage.get_distinct_did_count("", "", "")?, 0); 147 assert_eq!( 148 - storage.get_links("a.com", "app.t.c", ".abc.uri", 100, None)?, 149 PagedAppendingCollection { 150 version: (0, 0), 151 items: vec![], ··· 641 0, 642 )?; 643 assert_eq!( 644 - storage.get_links("a.com", "app.t.c", ".abc.uri", 100, None)?, 645 PagedAppendingCollection { 646 version: (1, 0), 647 items: vec![RecordId { ··· 682 0, 683 )?; 684 } 685 - let links = storage.get_links("a.com", "app.t.c", ".abc.uri", 2, None)?; 686 let dids = storage.get_distinct_dids("a.com", "app.t.c", ".abc.uri", 2, None)?; 687 assert_eq!( 688 links, ··· 713 total: 5, 714 } 715 ); 716 - let links = storage.get_links("a.com", "app.t.c", ".abc.uri", 2, links.next)?; 717 let dids = storage.get_distinct_dids("a.com", "app.t.c", ".abc.uri", 2, dids.next)?; 718 assert_eq!( 719 links, ··· 744 total: 5, 745 } 746 ); 747 - let links = storage.get_links("a.com", "app.t.c", ".abc.uri", 2, links.next)?; 748 let dids = storage.get_distinct_dids("a.com", "app.t.c", ".abc.uri", 2, dids.next)?; 749 assert_eq!( 750 links, ··· 771 assert_stats(storage.get_stats()?, 5..=5, 1..=1, 5..=5); 772 }); 773 774 test_each_storage!(get_links_exact_multiple, |storage| { 775 for i in 1..=4 { 776 storage.push( ··· 788 0, 789 )?; 790 } 791 - let links = storage.get_links("a.com", "app.t.c", ".abc.uri", 2, None)?; 792 assert_eq!( 793 links, 794 PagedAppendingCollection { ··· 809 total: 4, 810 } 811 ); 812 - let links = storage.get_links("a.com", "app.t.c", ".abc.uri", 2, links.next)?; 813 assert_eq!( 814 links, 815 PagedAppendingCollection { ··· 850 0, 851 )?; 852 } 853 - let links = storage.get_links("a.com", "app.t.c", ".abc.uri", 2, None)?; 854 assert_eq!( 855 links, 856 PagedAppendingCollection { ··· 885 }, 886 0, 887 )?; 888 - let links = storage.get_links("a.com", "app.t.c", ".abc.uri", 2, links.next)?; 889 assert_eq!( 890 links, 891 PagedAppendingCollection { ··· 926 0, 927 )?; 928 } 929 - let links = storage.get_links("a.com", "app.t.c", ".abc.uri", 2, None)?; 930 assert_eq!( 931 links, 932 PagedAppendingCollection { ··· 955 }), 956 0, 957 )?; 958 - let links = storage.get_links("a.com", "app.t.c", ".abc.uri", 2, links.next)?; 959 assert_eq!( 960 links, 961 PagedAppendingCollection { ··· 989 0, 990 )?; 991 } 992 - let links = storage.get_links("a.com", "app.t.c", ".abc.uri", 2, None)?; 993 assert_eq!( 994 links, 995 PagedAppendingCollection { ··· 1014 &ActionableEvent::DeactivateAccount("did:plc:asdf-1".into()), 1015 0, 1016 )?; 1017 - let links = storage.get_links("a.com", "app.t.c", ".abc.uri", 2, links.next)?; 1018 assert_eq!( 1019 links, 1020 PagedAppendingCollection {
··· 1 use crate::{ActionableEvent, CountsByCount, Did, RecordId}; 2 use anyhow::Result; 3 use serde::{Deserialize, Serialize}; 4 + use std::collections::{HashMap, HashSet}; 5 6 pub mod mem_store; 7 pub use mem_store::MemStorage; ··· 59 path: &str, 60 limit: u64, 61 until: Option<u64>, 62 + filter_dids: &HashSet<Did>, 63 ) -> Result<PagedAppendingCollection<RecordId>>; 64 65 fn get_distinct_dids( ··· 146 ); 147 assert_eq!(storage.get_distinct_did_count("", "", "")?, 0); 148 assert_eq!( 149 + storage.get_links( 150 + "a.com", 151 + "app.t.c", 152 + ".abc.uri", 153 + 100, 154 + None, 155 + &HashSet::default() 156 + )?, 157 PagedAppendingCollection { 158 version: (0, 0), 159 items: vec![], ··· 649 0, 650 )?; 651 assert_eq!( 652 + storage.get_links( 653 + "a.com", 654 + "app.t.c", 655 + ".abc.uri", 656 + 100, 657 + None, 658 + &HashSet::default() 659 + )?, 660 PagedAppendingCollection { 661 version: (1, 0), 662 items: vec![RecordId { ··· 697 0, 698 )?; 699 } 700 + let links = 701 + storage.get_links("a.com", "app.t.c", ".abc.uri", 2, None, &HashSet::default())?; 702 let dids = storage.get_distinct_dids("a.com", "app.t.c", ".abc.uri", 2, None)?; 703 assert_eq!( 704 links, ··· 729 total: 5, 730 } 731 ); 732 + let links = storage.get_links( 733 + "a.com", 734 + "app.t.c", 735 + ".abc.uri", 736 + 2, 737 + links.next, 738 + &HashSet::default(), 739 + )?; 740 let dids = storage.get_distinct_dids("a.com", "app.t.c", ".abc.uri", 2, dids.next)?; 741 assert_eq!( 742 links, ··· 767 total: 5, 768 } 769 ); 770 + let links = storage.get_links( 771 + "a.com", 772 + "app.t.c", 773 + ".abc.uri", 774 + 2, 775 + links.next, 776 + &HashSet::default(), 777 + )?; 778 let dids = storage.get_distinct_dids("a.com", "app.t.c", ".abc.uri", 2, dids.next)?; 779 assert_eq!( 780 links, ··· 801 assert_stats(storage.get_stats()?, 5..=5, 1..=1, 5..=5); 802 }); 803 804 + test_each_storage!(get_filtered_links, |storage| { 805 + let links = storage.get_links( 806 + "a.com", 807 + "app.t.c", 808 + ".abc.uri", 809 + 2, 810 + None, 811 + &HashSet::from([Did("did:plc:linker".to_string())]), 812 + )?; 813 + assert_eq!( 814 + links, 815 + PagedAppendingCollection { 816 + version: (0, 0), 817 + items: vec![], 818 + next: None, 819 + total: 0, 820 + } 821 + ); 822 + 823 + storage.push( 824 + &ActionableEvent::CreateLinks { 825 + record_id: RecordId { 826 + did: "did:plc:linker".into(), 827 + collection: "app.t.c".into(), 828 + rkey: "asdf".into(), 829 + }, 830 + links: vec![CollectedLink { 831 + target: Link::Uri("a.com".into()), 832 + path: ".abc.uri".into(), 833 + }], 834 + }, 835 + 0, 836 + )?; 837 + 838 + let links = storage.get_links( 839 + "a.com", 840 + "app.t.c", 841 + ".abc.uri", 842 + 2, 843 + None, 844 + &HashSet::from([Did("did:plc:linker".to_string())]), 845 + )?; 846 + assert_eq!( 847 + links, 848 + PagedAppendingCollection { 849 + version: (1, 0), 850 + items: vec![RecordId { 851 + did: "did:plc:linker".into(), 852 + collection: "app.t.c".into(), 853 + rkey: "asdf".into(), 854 + },], 855 + next: None, 856 + total: 1, 857 + } 858 + ); 859 + 860 + let links = storage.get_links( 861 + "a.com", 862 + "app.t.c", 863 + ".abc.uri", 864 + 2, 865 + None, 866 + &HashSet::from([Did("did:plc:someone-else".to_string())]), 867 + )?; 868 + assert_eq!( 869 + links, 870 + PagedAppendingCollection { 871 + version: (0, 0), 872 + items: vec![], 873 + next: None, 874 + total: 0, 875 + } 876 + ); 877 + 878 + storage.push( 879 + &ActionableEvent::CreateLinks { 880 + record_id: RecordId { 881 + did: "did:plc:linker".into(), 882 + collection: "app.t.c".into(), 883 + rkey: "asdf-2".into(), 884 + }, 885 + links: vec![CollectedLink { 886 + target: Link::Uri("a.com".into()), 887 + path: ".abc.uri".into(), 888 + }], 889 + }, 890 + 0, 891 + )?; 892 + storage.push( 893 + &ActionableEvent::CreateLinks { 894 + record_id: RecordId { 895 + did: "did:plc:someone-else".into(), 896 + collection: "app.t.c".into(), 897 + rkey: "asdf".into(), 898 + }, 899 + links: vec![CollectedLink { 900 + target: Link::Uri("a.com".into()), 901 + path: ".abc.uri".into(), 902 + }], 903 + }, 904 + 0, 905 + )?; 906 + 907 + let links = storage.get_links( 908 + "a.com", 909 + "app.t.c", 910 + ".abc.uri", 911 + 2, 912 + None, 913 + &HashSet::from([Did("did:plc:linker".to_string())]), 914 + )?; 915 + assert_eq!( 916 + links, 917 + PagedAppendingCollection { 918 + version: (2, 0), 919 + items: vec![ 920 + RecordId { 921 + did: "did:plc:linker".into(), 922 + collection: "app.t.c".into(), 923 + rkey: "asdf-2".into(), 924 + }, 925 + RecordId { 926 + did: "did:plc:linker".into(), 927 + collection: "app.t.c".into(), 928 + rkey: "asdf".into(), 929 + }, 930 + ], 931 + next: None, 932 + total: 2, 933 + } 934 + ); 935 + 936 + let links = storage.get_links( 937 + "a.com", 938 + "app.t.c", 939 + ".abc.uri", 940 + 2, 941 + None, 942 + &HashSet::from([ 943 + Did("did:plc:linker".to_string()), 944 + Did("did:plc:someone-else".to_string()), 945 + ]), 946 + )?; 947 + assert_eq!( 948 + links, 949 + PagedAppendingCollection { 950 + version: (3, 0), 951 + items: vec![ 952 + RecordId { 953 + did: "did:plc:someone-else".into(), 954 + collection: "app.t.c".into(), 955 + rkey: "asdf".into(), 956 + }, 957 + RecordId { 958 + did: "did:plc:linker".into(), 959 + collection: "app.t.c".into(), 960 + rkey: "asdf-2".into(), 961 + }, 962 + ], 963 + next: Some(1), 964 + total: 3, 965 + } 966 + ); 967 + 968 + let links = storage.get_links( 969 + "a.com", 970 + "app.t.c", 971 + ".abc.uri", 972 + 2, 973 + None, 974 + &HashSet::from([Did("did:plc:someone-unknown".to_string())]), 975 + )?; 976 + assert_eq!( 977 + links, 978 + PagedAppendingCollection { 979 + version: (0, 0), 980 + items: vec![], 981 + next: None, 982 + total: 0, 983 + } 984 + ); 985 + }); 986 + 987 test_each_storage!(get_links_exact_multiple, |storage| { 988 for i in 1..=4 { 989 storage.push( ··· 1001 0, 1002 )?; 1003 } 1004 + let links = 1005 + storage.get_links("a.com", "app.t.c", ".abc.uri", 2, None, &HashSet::default())?; 1006 assert_eq!( 1007 links, 1008 PagedAppendingCollection { ··· 1023 total: 4, 1024 } 1025 ); 1026 + let links = storage.get_links( 1027 + "a.com", 1028 + "app.t.c", 1029 + ".abc.uri", 1030 + 2, 1031 + links.next, 1032 + &HashSet::default(), 1033 + )?; 1034 assert_eq!( 1035 links, 1036 PagedAppendingCollection { ··· 1071 0, 1072 )?; 1073 } 1074 + let links = 1075 + storage.get_links("a.com", "app.t.c", ".abc.uri", 2, None, &HashSet::default())?; 1076 assert_eq!( 1077 links, 1078 PagedAppendingCollection { ··· 1107 }, 1108 0, 1109 )?; 1110 + let links = storage.get_links( 1111 + "a.com", 1112 + "app.t.c", 1113 + ".abc.uri", 1114 + 2, 1115 + links.next, 1116 + &HashSet::default(), 1117 + )?; 1118 assert_eq!( 1119 links, 1120 PagedAppendingCollection { ··· 1155 0, 1156 )?; 1157 } 1158 + let links = 1159 + storage.get_links("a.com", "app.t.c", ".abc.uri", 2, None, &HashSet::default())?; 1160 assert_eq!( 1161 links, 1162 PagedAppendingCollection { ··· 1185 }), 1186 0, 1187 )?; 1188 + let links = storage.get_links( 1189 + "a.com", 1190 + "app.t.c", 1191 + ".abc.uri", 1192 + 2, 1193 + links.next, 1194 + &HashSet::default(), 1195 + )?; 1196 assert_eq!( 1197 links, 1198 PagedAppendingCollection { ··· 1226 0, 1227 )?; 1228 } 1229 + let links = 1230 + storage.get_links("a.com", "app.t.c", ".abc.uri", 2, None, &HashSet::default())?; 1231 assert_eq!( 1232 links, 1233 PagedAppendingCollection { ··· 1252 &ActionableEvent::DeactivateAccount("did:plc:asdf-1".into()), 1253 0, 1254 )?; 1255 + let links = storage.get_links( 1256 + "a.com", 1257 + "app.t.c", 1258 + ".abc.uri", 1259 + 2, 1260 + links.next, 1261 + &HashSet::default(), 1262 + )?; 1263 assert_eq!( 1264 links, 1265 PagedAppendingCollection {
+19 -1
constellation/src/storage/rocks_store.rs
··· 860 path: &str, 861 limit: u64, 862 until: Option<u64>, 863 ) -> Result<PagedAppendingCollection<RecordId>> { 864 let target_key = TargetKey( 865 Target(target.to_string()), ··· 876 }); 877 }; 878 879 - let linkers = self.get_target_linkers(&target_id)?; 880 881 let (alive, gone) = linkers.count(); 882 let total = alive + gone;
··· 860 path: &str, 861 limit: u64, 862 until: Option<u64>, 863 + filter_dids: &HashSet<Did>, 864 ) -> Result<PagedAppendingCollection<RecordId>> { 865 let target_key = TargetKey( 866 Target(target.to_string()), ··· 877 }); 878 }; 879 880 + let mut linkers = self.get_target_linkers(&target_id)?; 881 + if !filter_dids.is_empty() { 882 + let mut did_filter = HashSet::new(); 883 + for did in filter_dids { 884 + let Some(DidIdValue(did_id, active)) = 885 + self.did_id_table.get_id_val(&self.db, did)? 886 + else { 887 + eprintln!("failed to find a did_id for {did:?}"); 888 + continue; 889 + }; 890 + if !active { 891 + eprintln!("excluding inactive did from filtered results"); 892 + continue; 893 + } 894 + did_filter.insert(did_id); 895 + } 896 + linkers.0.retain(|linker| did_filter.contains(&linker.0)); 897 + } 898 899 let (alive, gone) = linkers.count(); 900 let total = alive + gone;
+9 -6
constellation/templates/hello.html.j2
··· 20 21 <p> 22 This server has indexed <span class="stat">{{ stats.linking_records|human_number }}</span> links between <span class="stat">{{ stats.targetables|human_number }}</span> targets and sources from <span class="stat">{{ stats.dids|human_number }}</span> identities over <span class="stat">{{ days_indexed|human_number }}</span> days.<br/> 23 - <small>(indexing new records in real time, backfill still TODO)</small> 24 </p> 25 26 - <p>The API is currently <strong>unstable</strong>. But feel free to use it! If you want to be nice, put your project name and bsky username (or email) in your user-agent header for api requests.</p> 27 28 29 <h2>API Endpoints</h2> ··· 35 <h4>Query parameters:</h4> 36 37 <ul> 38 - <li><code>target</code>: required, must url-encode. Example: <code>at://did:plc:vc7f4oafdgxsihk4cry2xpze/app.bsky.feed.post/3lgwdn7vd722r</code></li> 39 - <li><code>collection</code>: required. Example: <code>app.bsky.feed.like</code></li> 40 - <li><code>path</code>: required, must url-encode. Example: <code>.subject.uri</code></li> 41 </ul> 42 43 <p style="margin-bottom: 0"><strong>Try it:</strong></p> 44 - {% call try_it::links("at://did:plc:vc7f4oafdgxsihk4cry2xpze/app.bsky.feed.post/3lgwdn7vd722r", "app.bsky.feed.like", ".subject.uri") %} 45 46 47 <h3 class="route"><code>GET /links/distinct-dids</code></h3>
··· 20 21 <p> 22 This server has indexed <span class="stat">{{ stats.linking_records|human_number }}</span> links between <span class="stat">{{ stats.targetables|human_number }}</span> targets and sources from <span class="stat">{{ stats.dids|human_number }}</span> identities over <span class="stat">{{ days_indexed|human_number }}</span> days.<br/> 23 + <small>(indexing new records in real time, backfill coming soon!)</small> 24 </p> 25 26 + <p>But feel free to use it! If you want to be nice, put your project name and bsky username (or email) in your user-agent header for api requests.</p> 27 28 29 <h2>API Endpoints</h2> ··· 35 <h4>Query parameters:</h4> 36 37 <ul> 38 + <li><p><code>target</code>: required, must url-encode. Example: <code>at://did:plc:vc7f4oafdgxsihk4cry2xpze/app.bsky.feed.post/3lgwdn7vd722r</code></p></li> 39 + <li><p><code>collection</code>: required. Example: <code>app.bsky.feed.like</code></p></li> 40 + <li><p><code>path</code>: required, must url-encode. Example: <code>.subject.uri</code></p></li> 41 + <li><p><code>did</code>: optional, filter links to those from specific users. Include multiple times to filter by multiple users. Example: <code>did=did:plc:vc7f4oafdgxsihk4cry2xpze&did=did:plc:vc7f4oafdgxsihk4cry2xpze</code></p></li> 42 + <li><p><code>from_dids</code> [deprecated]: optional. Use <code>did</code> instead. Example: <code>from_dids=did:plc:vc7f4oafdgxsihk4cry2xpze,did:plc:vc7f4oafdgxsihk4cry2xpze</code></p></li> 43 + <li><p><code>limit</code>: optional. Default: <code>16</code>. Maximum: <code>100</code></p></li> 44 </ul> 45 46 <p style="margin-bottom: 0"><strong>Try it:</strong></p> 47 + {% call try_it::links("at://did:plc:a4pqq234yw7fqbddawjo7y35/app.bsky.feed.post/3m237ilwc372e", "app.bsky.feed.like", ".subject.uri", [""], 16) %} 48 49 50 <h3 class="route"><code>GET /links/distinct-dids</code></h3>
+1 -1
constellation/templates/links.html.j2
··· 6 7 {% block content %} 8 9 - {% call try_it::links(query.target, query.collection, query.path) %} 10 11 <h2> 12 Links to <code>{{ query.target }}</code>
··· 6 7 {% block content %} 8 9 + {% call try_it::links(query.target, query.collection, query.path, query.did, query.limit) %} 10 11 <h2> 12 Links to <code>{{ query.target }}</code>
+20 -2
constellation/templates/try-it-macros.html.j2
··· 1 - {% macro links(target, collection, path) %} 2 <form method="get" action="/links"> 3 <pre class="code"><strong>GET</strong> /links 4 ?target= <input type="text" name="target" value="{{ target }}" placeholder="target" /> 5 &collection= <input type="text" name="collection" value="{{ collection }}" placeholder="collection" /> 6 - &path= <input type="text" name="path" value="{{ path }}" placeholder="path" /> <button type="submit">get links</button></pre> 7 </form> 8 {% endmacro %} 9 10
··· 1 + {% macro links(target, collection, path, dids, limit) %} 2 <form method="get" action="/links"> 3 <pre class="code"><strong>GET</strong> /links 4 ?target= <input type="text" name="target" value="{{ target }}" placeholder="target" /> 5 &collection= <input type="text" name="collection" value="{{ collection }}" placeholder="collection" /> 6 + &path= <input type="text" name="path" value="{{ path }}" placeholder="path" /> 7 + {%- for did in dids %}{% if !did.is_empty() %} 8 + &did= <input type="text" name="did" value="{{ did }}" placeholder="did:plc:..." />{% endif %}{% endfor %} 9 + <span id="did-placeholder"></span> <button id="add-did">+ did filter</button> 10 + &limit= <input type="number" name="limit" value="{{ limit }}" max="100" placeholder="100" /> <button type="submit">get links</button></pre> 11 </form> 12 + <script> 13 + const addDidButton = document.getElementById('add-did'); 14 + const didPlaceholder = document.getElementById('did-placeholder'); 15 + addDidButton.addEventListener('click', e => { 16 + e.preventDefault(); 17 + const i = document.createElement('input'); 18 + i.placeholder = 'did:plc:...'; 19 + i.name = "did" 20 + const p = addDidButton.parentNode; 21 + p.insertBefore(document.createTextNode('&did= '), didPlaceholder); 22 + p.insertBefore(i, didPlaceholder); 23 + p.insertBefore(document.createTextNode('\n '), didPlaceholder); 24 + }); 25 + </script> 26 {% endmacro %} 27 28
+6 -7
reflector/src/main.rs
··· 44 Data(parent): Data<&Option<String>>, 45 Query(AskQuery { domain }): Query<AskQuery>, 46 ) -> Response { 47 - if let Some(parent) = parent { 48 - if let Some(prefix) = domain.strip_suffix(&format!(".{parent}")) { 49 - if !prefix.contains('.') { 50 - // no sub-sub-domains allowed 51 - return Response::builder().body("ok"); 52 - } 53 - } 54 }; 55 Response::builder() 56 .status(StatusCode::FORBIDDEN)
··· 44 Data(parent): Data<&Option<String>>, 45 Query(AskQuery { domain }): Query<AskQuery>, 46 ) -> Response { 47 + if let Some(parent) = parent 48 + && let Some(prefix) = domain.strip_suffix(&format!(".{parent}")) 49 + && !prefix.contains('.') 50 + { 51 + // no sub-sub-domains allowed 52 + return Response::builder().body("ok"); 53 }; 54 Response::builder() 55 .status(StatusCode::FORBIDDEN)
+5 -5
spacedust/src/subscriber.rs
··· 42 loop { 43 tokio::select! { 44 l = receiver.recv() => match l { 45 - Ok(link) => if self.filter(&link.properties) { 46 - if let Err(e) = ws_sender.send(link.message.clone()).await { 47 - log::warn!("failed to send link, dropping subscriber: {e:?}"); 48 - break; 49 - } 50 }, 51 Err(RecvError::Closed) => self.shutdown.cancel(), 52 Err(RecvError::Lagged(n)) => {
··· 42 loop { 43 tokio::select! { 44 l = receiver.recv() => match l { 45 + Ok(link) => if self.filter(&link.properties) 46 + && let Err(e) = ws_sender.send(link.message.clone()).await 47 + { 48 + log::warn!("failed to send link, dropping subscriber: {e:?}"); 49 + break; 50 }, 51 Err(RecvError::Closed) => self.shutdown.cancel(), 52 Err(RecvError::Lagged(n)) => {
+4 -4
who-am-i/src/server.rs
··· 268 Some(parent_host), 269 ); 270 } 271 - if let Some(ref app) = params.app { 272 - if !allowed_hosts.contains(app) { 273 - return err("Login is not allowed for this app", false, Some(app)); 274 - } 275 } 276 let parent_origin = url.origin().ascii_serialization(); 277 if parent_origin == "null" {
··· 268 Some(parent_host), 269 ); 270 } 271 + if let Some(ref app) = params.app 272 + && !allowed_hosts.contains(app) 273 + { 274 + return err("Login is not allowed for this app", false, Some(app)); 275 } 276 let parent_origin = url.origin().ascii_serialization(); 277 if parent_origin == "null" {