CLI tool for migrating PDS

Migrate identity and finalise migration

Changed files
+443 -3
src
+298
Cargo.lock
··· 130 130 ] 131 131 132 132 [[package]] 133 + name = "atrium-crypto" 134 + version = "0.1.2" 135 + source = "registry+https://github.com/rust-lang/crates.io-index" 136 + checksum = "73a3da430c71dd9006d61072c20771f264e5c498420a49c32305ceab8bd71955" 137 + dependencies = [ 138 + "ecdsa", 139 + "k256", 140 + "multibase", 141 + "p256", 142 + "thiserror 1.0.69", 143 + ] 144 + 145 + [[package]] 133 146 name = "atrium-identity" 134 147 version = "0.1.1" 135 148 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 196 209 version = "0.2.11" 197 210 source = "registry+https://github.com/rust-lang/crates.io-index" 198 211 checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" 212 + 213 + [[package]] 214 + name = "base16ct" 215 + version = "0.2.0" 216 + source = "registry+https://github.com/rust-lang/crates.io-index" 217 + checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" 199 218 200 219 [[package]] 201 220 name = "base64" ··· 204 223 checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 205 224 206 225 [[package]] 226 + name = "base64ct" 227 + version = "1.7.3" 228 + source = "registry+https://github.com/rust-lang/crates.io-index" 229 + checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" 230 + 231 + [[package]] 207 232 name = "bitflags" 208 233 version = "2.9.0" 209 234 source = "registry+https://github.com/rust-lang/crates.io-index" 210 235 checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" 236 + 237 + [[package]] 238 + name = "block-buffer" 239 + version = "0.10.4" 240 + source = "registry+https://github.com/rust-lang/crates.io-index" 241 + checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 242 + dependencies = [ 243 + "generic-array", 244 + ] 211 245 212 246 [[package]] 213 247 name = "bumpalo" ··· 281 315 ] 282 316 283 317 [[package]] 318 + name = "const-oid" 319 + version = "0.9.6" 320 + source = "registry+https://github.com/rust-lang/crates.io-index" 321 + checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" 322 + 323 + [[package]] 284 324 name = "core-foundation" 285 325 version = "0.9.4" 286 326 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 303 343 checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" 304 344 dependencies = [ 305 345 "memchr", 346 + ] 347 + 348 + [[package]] 349 + name = "cpufeatures" 350 + version = "0.2.17" 351 + source = "registry+https://github.com/rust-lang/crates.io-index" 352 + checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" 353 + dependencies = [ 354 + "libc", 306 355 ] 307 356 308 357 [[package]] ··· 345 394 checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 346 395 347 396 [[package]] 397 + name = "crypto-bigint" 398 + version = "0.5.5" 399 + source = "registry+https://github.com/rust-lang/crates.io-index" 400 + checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" 401 + dependencies = [ 402 + "generic-array", 403 + "rand_core 0.6.4", 404 + "subtle", 405 + "zeroize", 406 + ] 407 + 408 + [[package]] 409 + name = "crypto-common" 410 + version = "0.1.6" 411 + source = "registry+https://github.com/rust-lang/crates.io-index" 412 + checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 413 + dependencies = [ 414 + "generic-array", 415 + "typenum", 416 + ] 417 + 418 + [[package]] 348 419 name = "dashmap" 349 420 version = "6.1.0" 350 421 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 385 456 ] 386 457 387 458 [[package]] 459 + name = "der" 460 + version = "0.7.9" 461 + source = "registry+https://github.com/rust-lang/crates.io-index" 462 + checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" 463 + dependencies = [ 464 + "const-oid", 465 + "zeroize", 466 + ] 467 + 468 + [[package]] 469 + name = "digest" 470 + version = "0.10.7" 471 + source = "registry+https://github.com/rust-lang/crates.io-index" 472 + checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 473 + dependencies = [ 474 + "block-buffer", 475 + "const-oid", 476 + "crypto-common", 477 + "subtle", 478 + ] 479 + 480 + [[package]] 388 481 name = "displaydoc" 389 482 version = "0.2.5" 390 483 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 396 489 ] 397 490 398 491 [[package]] 492 + name = "ecdsa" 493 + version = "0.16.9" 494 + source = "registry+https://github.com/rust-lang/crates.io-index" 495 + checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" 496 + dependencies = [ 497 + "der", 498 + "digest", 499 + "elliptic-curve", 500 + "rfc6979", 501 + "signature", 502 + "spki", 503 + ] 504 + 505 + [[package]] 506 + name = "elliptic-curve" 507 + version = "0.13.8" 508 + source = "registry+https://github.com/rust-lang/crates.io-index" 509 + checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" 510 + dependencies = [ 511 + "base16ct", 512 + "crypto-bigint", 513 + "digest", 514 + "ff", 515 + "generic-array", 516 + "group", 517 + "pkcs8", 518 + "rand_core 0.6.4", 519 + "sec1", 520 + "subtle", 521 + "zeroize", 522 + ] 523 + 524 + [[package]] 399 525 name = "enum-as-inner" 400 526 version = "0.6.1" 401 527 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 449 575 version = "2.3.0" 450 576 source = "registry+https://github.com/rust-lang/crates.io-index" 451 577 checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 578 + 579 + [[package]] 580 + name = "ff" 581 + version = "0.13.1" 582 + source = "registry+https://github.com/rust-lang/crates.io-index" 583 + checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" 584 + dependencies = [ 585 + "rand_core 0.6.4", 586 + "subtle", 587 + ] 452 588 453 589 [[package]] 454 590 name = "flate2" ··· 568 704 ] 569 705 570 706 [[package]] 707 + name = "generic-array" 708 + version = "0.14.7" 709 + source = "registry+https://github.com/rust-lang/crates.io-index" 710 + checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 711 + dependencies = [ 712 + "typenum", 713 + "version_check", 714 + "zeroize", 715 + ] 716 + 717 + [[package]] 571 718 name = "getrandom" 572 719 version = "0.2.15" 573 720 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 597 744 checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 598 745 599 746 [[package]] 747 + name = "group" 748 + version = "0.13.0" 749 + source = "registry+https://github.com/rust-lang/crates.io-index" 750 + checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" 751 + dependencies = [ 752 + "ff", 753 + "rand_core 0.6.4", 754 + "subtle", 755 + ] 756 + 757 + [[package]] 600 758 name = "hashbrown" 601 759 version = "0.14.5" 602 760 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 618 776 version = "0.5.0" 619 777 source = "registry+https://github.com/rust-lang/crates.io-index" 620 778 checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 779 + 780 + [[package]] 781 + name = "hex" 782 + version = "0.4.3" 783 + source = "registry+https://github.com/rust-lang/crates.io-index" 784 + checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 621 785 622 786 [[package]] 623 787 name = "hickory-proto" ··· 691 855 ] 692 856 693 857 [[package]] 858 + name = "hmac" 859 + version = "0.12.1" 860 + source = "registry+https://github.com/rust-lang/crates.io-index" 861 + checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 862 + dependencies = [ 863 + "digest", 864 + ] 865 + 866 + [[package]] 694 867 name = "hostname" 695 868 version = "0.4.0" 696 869 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1013 1186 ] 1014 1187 1015 1188 [[package]] 1189 + name = "k256" 1190 + version = "0.13.4" 1191 + source = "registry+https://github.com/rust-lang/crates.io-index" 1192 + checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" 1193 + dependencies = [ 1194 + "cfg-if", 1195 + "ecdsa", 1196 + "elliptic-curve", 1197 + "sha2", 1198 + ] 1199 + 1200 + [[package]] 1016 1201 name = "langtag" 1017 1202 version = "0.3.4" 1018 1203 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1274 1459 checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 1275 1460 1276 1461 [[package]] 1462 + name = "p256" 1463 + version = "0.13.2" 1464 + source = "registry+https://github.com/rust-lang/crates.io-index" 1465 + checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" 1466 + dependencies = [ 1467 + "ecdsa", 1468 + "elliptic-curve", 1469 + "primeorder", 1470 + "sha2", 1471 + ] 1472 + 1473 + [[package]] 1277 1474 name = "parking" 1278 1475 version = "2.2.1" 1279 1476 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1308 1505 dependencies = [ 1309 1506 "atrium-api", 1310 1507 "atrium-common", 1508 + "atrium-crypto", 1311 1509 "atrium-identity", 1312 1510 "atrium-xrpc-client", 1511 + "hex", 1313 1512 "hickory-resolver", 1513 + "rand 0.8.5", 1314 1514 "tokio", 1315 1515 ] 1316 1516 ··· 1333 1533 checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1334 1534 1335 1535 [[package]] 1536 + name = "pkcs8" 1537 + version = "0.10.2" 1538 + source = "registry+https://github.com/rust-lang/crates.io-index" 1539 + checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" 1540 + dependencies = [ 1541 + "der", 1542 + "spki", 1543 + ] 1544 + 1545 + [[package]] 1336 1546 name = "pkg-config" 1337 1547 version = "0.3.32" 1338 1548 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1351 1561 checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" 1352 1562 dependencies = [ 1353 1563 "zerocopy 0.7.35", 1564 + ] 1565 + 1566 + [[package]] 1567 + name = "primeorder" 1568 + version = "0.13.6" 1569 + source = "registry+https://github.com/rust-lang/crates.io-index" 1570 + checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" 1571 + dependencies = [ 1572 + "elliptic-curve", 1354 1573 ] 1355 1574 1356 1575 [[package]] ··· 1536 1755 ] 1537 1756 1538 1757 [[package]] 1758 + name = "rfc6979" 1759 + version = "0.4.0" 1760 + source = "registry+https://github.com/rust-lang/crates.io-index" 1761 + checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" 1762 + dependencies = [ 1763 + "hmac", 1764 + "subtle", 1765 + ] 1766 + 1767 + [[package]] 1539 1768 name = "ring" 1540 1769 version = "0.17.14" 1541 1770 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1624 1853 version = "1.2.0" 1625 1854 source = "registry+https://github.com/rust-lang/crates.io-index" 1626 1855 checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1856 + 1857 + [[package]] 1858 + name = "sec1" 1859 + version = "0.7.3" 1860 + source = "registry+https://github.com/rust-lang/crates.io-index" 1861 + checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" 1862 + dependencies = [ 1863 + "base16ct", 1864 + "der", 1865 + "generic-array", 1866 + "pkcs8", 1867 + "subtle", 1868 + "zeroize", 1869 + ] 1627 1870 1628 1871 [[package]] 1629 1872 name = "security-framework" ··· 1721 1964 ] 1722 1965 1723 1966 [[package]] 1967 + name = "sha2" 1968 + version = "0.10.8" 1969 + source = "registry+https://github.com/rust-lang/crates.io-index" 1970 + checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 1971 + dependencies = [ 1972 + "cfg-if", 1973 + "cpufeatures", 1974 + "digest", 1975 + ] 1976 + 1977 + [[package]] 1724 1978 name = "sharded-slab" 1725 1979 version = "0.1.7" 1726 1980 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1736 1990 checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1737 1991 1738 1992 [[package]] 1993 + name = "signature" 1994 + version = "2.2.0" 1995 + source = "registry+https://github.com/rust-lang/crates.io-index" 1996 + checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" 1997 + dependencies = [ 1998 + "digest", 1999 + "rand_core 0.6.4", 2000 + ] 2001 + 2002 + [[package]] 1739 2003 name = "slab" 1740 2004 version = "0.4.9" 1741 2005 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1761 2025 ] 1762 2026 1763 2027 [[package]] 2028 + name = "spki" 2029 + version = "0.7.3" 2030 + source = "registry+https://github.com/rust-lang/crates.io-index" 2031 + checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" 2032 + dependencies = [ 2033 + "base64ct", 2034 + "der", 2035 + ] 2036 + 2037 + [[package]] 1764 2038 name = "stable_deref_trait" 1765 2039 version = "1.2.0" 1766 2040 source = "registry+https://github.com/rust-lang/crates.io-index" 1767 2041 checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 2042 + 2043 + [[package]] 2044 + name = "subtle" 2045 + version = "2.6.1" 2046 + source = "registry+https://github.com/rust-lang/crates.io-index" 2047 + checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 1768 2048 1769 2049 [[package]] 1770 2050 name = "syn" ··· 2048 2328 checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 2049 2329 2050 2330 [[package]] 2331 + name = "typenum" 2332 + version = "1.18.0" 2333 + source = "registry+https://github.com/rust-lang/crates.io-index" 2334 + checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" 2335 + 2336 + [[package]] 2051 2337 name = "unicode-ident" 2052 2338 version = "1.0.18" 2053 2339 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2108 2394 version = "0.2.15" 2109 2395 source = "registry+https://github.com/rust-lang/crates.io-index" 2110 2396 checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 2397 + 2398 + [[package]] 2399 + name = "version_check" 2400 + version = "0.9.5" 2401 + source = "registry+https://github.com/rust-lang/crates.io-index" 2402 + checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 2111 2403 2112 2404 [[package]] 2113 2405 name = "want" ··· 2698 2990 "syn", 2699 2991 "synstructure", 2700 2992 ] 2993 + 2994 + [[package]] 2995 + name = "zeroize" 2996 + version = "1.8.1" 2997 + source = "registry+https://github.com/rust-lang/crates.io-index" 2998 + checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 2701 2999 2702 3000 [[package]] 2703 3001 name = "zerovec"
+3
Cargo.toml
··· 6 6 [dependencies] 7 7 atrium-api = { version = "0.25.0", default-features = false, features = ["agent", "bluesky"] } 8 8 atrium-common = "0.1.0" 9 + atrium-crypto = "0.1.2" 9 10 atrium-identity = { version = "0.1.1", features = ["doh-handle-resolver"] } 10 11 atrium-xrpc-client = "0.5.11" 12 + hex = "0.4.3" 11 13 hickory-resolver = "0.25.1" 14 + rand = "0.8.5" 12 15 tokio = { version = "1.44.0", features = ["macros", "rt-multi-thread"]}
+142 -3
src/main.rs
··· 5 5 }, 6 6 app::bsky::actor::{get_preferences, put_preferences}, 7 7 com::atproto::{ 8 - server::{create_account, get_service_auth}, 8 + identity::sign_plc_operation, 9 + server::{create_account, deactivate_account, get_service_auth}, 9 10 sync::{get_blob, get_repo, list_blobs}, 10 11 }, 11 12 types::string::{Did, Handle, Nsid}, 12 13 }; 13 14 use atrium_common::resolver::Resolver; 15 + use atrium_crypto::keypair::{Did as _, Export, Secp256k1Keypair}; 14 16 use atrium_identity::{ 15 17 did::{CommonDidResolver, CommonDidResolverConfig}, 16 18 handle::{AtprotoHandleResolver, AtprotoHandleResolverConfig, DnsTxtResolver}, ··· 327 329 match new_agent.api.com.atproto.repo.upload_blob(blob).await { 328 330 Ok(_) => { 329 331 println!("Blob with CID {:?} migrated", cid) 330 - }, 332 + } 331 333 Err(err) => { 332 334 println!("com.atproto.repo.uploadBlob at new PDS failed due to error: {err}"); 333 335 return; ··· 385 387 match new_agent.api.com.atproto.repo.upload_blob(blob).await { 386 388 Ok(_) => { 387 389 println!("Blob with CID {:?} migrated", cid) 388 - }, 390 + } 389 391 Err(err) => { 390 392 println!("com.atproto.repo.uploadBlob at new PDS failed due to error: {err}"); 391 393 return; ··· 431 433 } 432 434 } 433 435 println!("Preferences successfully migrated!"); 436 + 437 + // Update identity 438 + println!("Migrating you identity (DID document) ..."); 439 + 440 + let pds_credentials = match new_agent 441 + .api 442 + .com 443 + .atproto 444 + .identity 445 + .get_recommended_did_credentials() 446 + .await 447 + { 448 + Ok(response) => response, 449 + Err(err) => { 450 + println!("com.atproto.identity.getRecommendedDidCredentials at new PDS failed due to error: {err}"); 451 + return; 452 + } 453 + }; 454 + 455 + match Did::new(identity.did.clone()).unwrap().method() { 456 + "plc" => { 457 + println!( 458 + "did:plc detected! Creating a recovery key and updating your DID document ..." 459 + ); 460 + let recovery_keypair = Secp256k1Keypair::create(&mut rand::thread_rng()); 461 + let private_key = hex::encode(recovery_keypair.export()); 462 + let mut recovery_keys = vec![recovery_keypair.did()]; 463 + if let Some(keys) = pds_credentials.rotation_keys.clone() { 464 + recovery_keys.extend(keys); 465 + } 466 + 467 + println!("PLC operations are potentially destructive therefore you will need to complete an email challenge with your current PDS"); 468 + if let Err(err) = current_agent 469 + .api 470 + .com 471 + .atproto 472 + .identity 473 + .request_plc_operation_signature() 474 + .await 475 + { 476 + println!("com.atproto.identity.requestPlcOperationSignature at current PDS failed due to error: {err}") 477 + }; 478 + let challenge_token = match readln(Some( 479 + "Challenge email sent. Please provide the token you where sent over email here", 480 + )) { 481 + Ok(token) => token, 482 + Err(err) => { 483 + println!("Could not read token due to error: {err}"); 484 + return; 485 + } 486 + }; 487 + println!("Your private recovery key is {private_key}. Please store this in a secure location!!"); 488 + if let Err(err) = readln(Some("Press enter once you've saved the key securely")) { 489 + println!("Could not handle enter due to error: {err}"); 490 + return; 491 + } 492 + 493 + match current_agent 494 + .api 495 + .com 496 + .atproto 497 + .identity 498 + .sign_plc_operation( 499 + sign_plc_operation::InputData { 500 + also_known_as: pds_credentials.also_known_as.clone(), 501 + rotation_keys: Some(recovery_keys), 502 + services: pds_credentials.services.clone(), 503 + token: Some(challenge_token.to_string()), 504 + verification_methods: pds_credentials.verification_methods.clone(), 505 + } 506 + .into(), 507 + ) 508 + .await 509 + { 510 + Ok(response) => response, 511 + Err(err) => { 512 + println!("com.atproto.identity.signPlcOperation at current PDS failed due to error: {err}"); 513 + return; 514 + } 515 + }; 516 + println!("DID document successfully updated!"); 517 + } 518 + "web" => { 519 + let did = identity.did; 520 + println!("did:web detected! Please manually update your DID document to match these values: {pds_credentials:#?}"); 521 + if let Err(err) = readln(Some("Press enter once you've updated your DID document")) { 522 + println!("Could not handle enter due to error: {err}"); 523 + return; 524 + } 525 + let mut valid_document = match identity_resolver.resolve(did.as_str()).await { 526 + Ok(response) => response.pds == new_pds_url.to_string(), 527 + Err(err) => { 528 + println!("Couldn't resolve DID {did} due to error: {err}"); 529 + return; 530 + } 531 + }; 532 + 533 + while !valid_document { 534 + println!("DID document not updated or updated incorretly! Needed PDS configuration: {new_pds_url}"); 535 + if let Err(err) = readln(Some("Press enter once you've updated your DID document")) 536 + { 537 + println!("Could not handle enter due to error: {err}"); 538 + return; 539 + } 540 + valid_document = match identity_resolver.resolve(did.as_str()).await { 541 + Ok(response) => response.pds == new_pds_url.to_string(), 542 + Err(err) => { 543 + println!("Couldn't resolve DID {did} due to error: {err}"); 544 + return; 545 + } 546 + }; 547 + } 548 + } 549 + _ => { 550 + println!("Unknown and invalid DID method found. This should not be possible!"); 551 + return; 552 + } 553 + } 554 + println!("Identity migrated successfully!"); 555 + 556 + // Finalise migration 557 + if let Err(err) = new_agent.api.com.atproto.server.activate_account().await { 558 + println!("com.atproto.server.activateAccount at new PDS failed due to error: {err}") 559 + }; 560 + if let Err(err) = current_agent 561 + .api 562 + .com 563 + .atproto 564 + .server 565 + .deactivate_account(deactivate_account::InputData { delete_after: None }.into()) 566 + .await 567 + { 568 + println!("com.atproto.server.activateAccount at current PDS failed due to error: {err}") 569 + }; 570 + 571 + println!("The account migration was successful!"); 572 + println!("The account on your old PDS has been deactivated. Please make sure everything works before fully deleting it in case you need to go back"); 434 573 }