Client side atproto account migrator in your web browser, along with services for backups and adversarial migrations.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

restore and npm fix

+264 -13
+5 -2
packages/lexicons/package.json
··· 2 2 "type": "module", 3 3 "name": "@pds-moover/lexicons", 4 4 "description": "PDS MOOver Lexicon Types", 5 - "version": "1.0.0", 5 + "version": "1.0.1", 6 6 "license": "MIT", 7 7 "repository": "https://tangled.org/@baileytownsend.dev/pds-moover", 8 + "files": [ 9 + "dist" 10 + ], 8 11 "exports": { 9 12 ".": "./dist/index.js", 10 13 "./types/*": "./dist/lexicons/types/sh/tangled/*.js" ··· 12 15 "scripts": { 13 16 "build": "tsc", 14 17 "generate": "rm -r ./lib/lexicons/; lex-cli generate -c ./lex.config.js", 15 - "prepublish": "rm -rf dist; pnpm run build" 18 + "prepublishOnly": "rm -rf dist; npm run build" 16 19 }, 17 20 "devDependencies": { 18 21 "@atcute/lex-cli": "^2.2.2"
+6 -2
packages/moover/lib/restore.js
··· 12 12 13 13 class Restore { 14 14 15 - constructor() { 15 + /** 16 + * 17 + * @param pdsMooverInstance {string} - The url of the pds moover instance to restore from. Defaults to https://pdsmover.com 18 + */ 19 + constructor(pdsMooverInstance = 'https://pdsmover.com') { 16 20 /** 17 21 * If you want to use a different plc directory create your own instance of the plc ops class and pass it in here 18 22 * @type {PlcOps} */ ··· 22 26 * This is the base url for the pds moover instance used to restore the files from a backup. 23 27 * @type {string} 24 28 */ 25 - this.pdsMooverInstance = 'https://pdsmover.com' 29 + this.pdsMooverInstance = pdsMooverInstance 26 30 27 31 /** 28 32 * To keep it simple, only uses secp256k for the temp verification key that is used to create the new account on the new PDS
+2 -2
packages/moover/types/backup.d.ts
··· 11 11 */ 12 12 export class BackupService { 13 13 /** 14 - * The did:web for the xrpc service for backups, defaults to pdsmoover.com 15 - * @param backupDidWeb 14 + * 15 + * @param backupDidWeb {string} - The did:web for the xrpc service for backups, defaults to did:web:pdsmoover.com 16 16 */ 17 17 constructor(backupDidWeb?: string); 18 18 /**
+1 -1
packages/moover/types/backup.d.ts.map
··· 1 - {"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../lib/backup.js"],"names":[],"mappings":";;;;AAKA;;;GAGG;AAGH;;GAEG;AACH;IACI;;;OAGG;IACH,mCAiBC;IAhBG;;;OAGG;IACH,cAFU,MAAM,CAEQ;IACxB;;;OAGG;IACH,yBAFU,iBAAiB,CAEQ;IAEnC;;;OAGG;IACH,cAFU,MAAM,CAEgB;IAIpC;;;;;;;;;;;;;;;OAeG;IACH,2BARsB,MAAM,YACR,MAAM,aACf,WAAS,IAAI,kBAEC,MAAM,GAAC,IAAI,GAEvB,OAAO,CAAC,mBAAmB,CAAC,gCAAgC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,GAAC,IAAI,CAAC,CAyDpG;IAED;;;;OAIG;IACH,wBAFa,OAAO,CAAC,IAAI,CAAC,CAczB;IAED;;;OAGG;IACH,oBAFa,OAAO,CAAC,IAAI,CAAC,CAgBzB;IAED;;;;;;;OAOG;IACH,6BAJoB,MAAM,eACH,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAgDzB;IAGD;;;;;;OAMG;IACH,8BAHoB,WAAS,IAAI,GACpB,OAAO,CAAC,mBAAmB,CAAC,gCAAgC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAe/F;IAED;;;;OAIG;IACH,8BAFa,OAAO,CAAC,OAAO,CAAC,CAkB5B;IAED;;;;OAIG;IACH,4BAFa,OAAO,CAAC,OAAO,CAAC,CAe5B;CACJ;uBAhR2C,gBAAgB;kCAAhB,gBAAgB;iDAGb,sBAAsB"} 1 + {"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../lib/backup.js"],"names":[],"mappings":";;;;AAKA;;;GAGG;AAGH;;GAEG;AACH;IACI;;;OAGG;IACH,2BAFwB,MAAM,EAmB7B;IAhBG;;;OAGG;IACH,cAFU,MAAM,CAEQ;IACxB;;;OAGG;IACH,yBAFU,iBAAiB,CAEQ;IAEnC;;;OAGG;IACH,cAFU,MAAM,CAEgB;IAIpC;;;;;;;;;;;;;;;OAeG;IACH,2BARsB,MAAM,YACR,MAAM,aACf,WAAS,IAAI,kBAEC,MAAM,GAAC,IAAI,GAEvB,OAAO,CAAC,mBAAmB,CAAC,gCAAgC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,GAAC,IAAI,CAAC,CAyDpG;IAED;;;;OAIG;IACH,wBAFa,OAAO,CAAC,IAAI,CAAC,CAczB;IAED;;;OAGG;IACH,oBAFa,OAAO,CAAC,IAAI,CAAC,CAgBzB;IAED;;;;;;;OAOG;IACH,6BAJoB,MAAM,eACH,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAgDzB;IAGD;;;;;;OAMG;IACH,8BAHoB,WAAS,IAAI,GACpB,OAAO,CAAC,mBAAmB,CAAC,gCAAgC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAe/F;IAED;;;;OAIG;IACH,8BAFa,OAAO,CAAC,OAAO,CAAC,CAkB5B;IAED;;;;OAIG;IACH,4BAFa,OAAO,CAAC,OAAO,CAAC,CAe5B;CACJ;uBAhR2C,gBAAgB;kCAAhB,gBAAgB;iDAGb,sBAAsB"}
+5
packages/moover/types/plc-ops.d.ts
··· 27 27 */ 28 28 export class PlcOps { 29 29 /** 30 + * 31 + * @param plcDirectoryUrl {string} - The url of the plc directory, defaults to https://plc.directory 32 + */ 33 + constructor(plcDirectoryUrl?: string); 34 + /** 30 35 * The url of the plc directory 31 36 * @type {string} 32 37 */
+1 -1
packages/moover/types/plc-ops.d.ts.map
··· 1 - {"version":3,"file":"plc-ops.d.ts","sourceRoot":"","sources":["../lib/plc-ops.js"],"names":[],"mappings":";;;;;;;;;;;wBAIa,OAAO,iBAAiB,EAAE,SAAS;;;;kCACnC,OAAO,iBAAiB,EAAE,mBAAmB;;;;8BAC7C,OAAO,iBAAiB,EAAE,eAAe;;;;2BACzC,OAAO,iBAAiB,EAAE,YAAY;AAgBnD;;GAEG;AACH;IAEQ;;;OAGG;IACH,iBAFU,MAAM,CAE8B;IAGlD;;;;OAIG;IACH,yCAFa,OAAO,CAAC,MAAM,EAAE,CAAC,CAM7B;IAED;;;;OAIG;IACH,+BAFa,OAAO,CAAC;QAAC,aAAa,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,GAAG,CAAA;KAAC,CAAC,CAK1D;IAED;;;;OAIG;IACH,mBAHgB,eAAe,GAClB;QAAC,aAAa,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,YAAY,CAAA;KAAC,CAK1D;IAGD;;;;OAIG;IACH,2BAFa,OAAO,CAAC,eAAe,CAAC,CAUpC;IAED;;;OAGG;IACH,uBAFa,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,WAAW,MAAM,EAAE,CAAA;KAAC,CAAC,CAUzE;IAGD;;;;;;;;;;OAUG;IACH,yBATe,MAAM,sBACU,cAAc,GAAC,mBAAmB,eAC1C,MAAM,EAAE,gBACP,MAAM,EAAE,OACjB,MAAM,mBACM,MAAM,QACjB,MAAM,GACT,OAAO,CAAC,IAAI,CAAC,CA6BzB;IAED;;;;;OAKG;IACH,6BAJ4B,MAAM,SAClB,MAAM,GACT,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,WAAW,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,cAAc,GAAC,mBAAmB,CAAA;KAAC,CAAC,CAmDnH;IAED;;;;;OAKG;IACH,sBAJe,MAAM,mBAER,OAAO,CAAC,IAAI,CAAC,CAwBzB;IAGD;;;;;;;;OAQG;IACH,wEAFa,OAAO,CAAC,MAAM,CAAC,CAwC3B;CAGJ;qBAzQ+B,iBAAiB;+BACsD,gBAAgB;oCAAhB,gBAAgB"} 1 + {"version":3,"file":"plc-ops.d.ts","sourceRoot":"","sources":["../lib/plc-ops.js"],"names":[],"mappings":";;;;;;;;;;;wBAIa,OAAO,iBAAiB,EAAE,SAAS;;;;kCACnC,OAAO,iBAAiB,EAAE,mBAAmB;;;;8BAC7C,OAAO,iBAAiB,EAAE,eAAe;;;;2BACzC,OAAO,iBAAiB,EAAE,YAAY;AAgBnD;;GAEG;AACH;IACI;;;OAGG;IACH,8BAF2B,MAAM,EAQhC;IALG;;;OAGG;IACH,iBAFU,MAAM,CAEsB;IAG1C;;;;OAIG;IACH,yCAFa,OAAO,CAAC,MAAM,EAAE,CAAC,CAM7B;IAED;;;;OAIG;IACH,+BAFa,OAAO,CAAC;QAAC,aAAa,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,GAAG,CAAA;KAAC,CAAC,CAK1D;IAED;;;;OAIG;IACH,mBAHgB,eAAe,GAClB;QAAC,aAAa,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,YAAY,CAAA;KAAC,CAK1D;IAGD;;;;OAIG;IACH,2BAFa,OAAO,CAAC,eAAe,CAAC,CAUpC;IAED;;;OAGG;IACH,uBAFa,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,WAAW,MAAM,EAAE,CAAA;KAAC,CAAC,CAUzE;IAGD;;;;;;;;;;OAUG;IACH,yBATe,MAAM,sBACU,cAAc,GAAC,mBAAmB,eAC1C,MAAM,EAAE,gBACP,MAAM,EAAE,OACjB,MAAM,mBACM,MAAM,QACjB,MAAM,GACT,OAAO,CAAC,IAAI,CAAC,CA6BzB;IAED;;;;;OAKG;IACH,6BAJ4B,MAAM,SAClB,MAAM,GACT,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,WAAW,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,cAAc,GAAC,mBAAmB,CAAA;KAAC,CAAC,CAmDnH;IAED;;;;;OAKG;IACH,sBAJe,MAAM,mBAER,OAAO,CAAC,IAAI,CAAC,CAwBzB;IAGD;;;;;;;;OAQG;IACH,wEAFa,OAAO,CAAC,MAAM,CAAC,CAwC3B;CAGJ;qBA7Q+B,iBAAiB;+BACsD,gBAAgB;oCAAhB,gBAAgB"}
+5
packages/moover/types/restore.d.ts
··· 1 1 export type Operation = import("@atcute/did-plc").Operation; 2 2 export class Restore { 3 3 /** 4 + * 5 + * @param pdsMooverInstance {string} - The url of the pds moover instance to restore from. Defaults to https://pdsmover.com 6 + */ 7 + constructor(pdsMooverInstance?: string); 8 + /** 4 9 * If you want to use a different plc directory create your own instance of the plc ops class and pass it in here 5 10 * @type {PlcOps} */ 6 11 plcOps: PlcOps;
+1 -1
packages/moover/types/restore.d.ts.map
··· 1 - {"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../lib/restore.js"],"names":[],"mappings":"wBACa,OAAO,iBAAiB,EAAE,SAAS;AAWhD;IAGQ;;wBAEoB;IACpB,QADU,MAAM,CACU;IAE1B;;;OAGG;IACH,mBAFU,MAAM,CAE+B;IAE/C;;;;OAIG;IACH,yBAFU,IAAI,GAAC,6BAA6B,CAET;IAEnC,uBAAuB;IACvB,UADW,QAAQ,CACC;IAEpB;;;OAGG;IACH,yBAFU,IAAI,GAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,WAAW,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,cAAc,GAAC,mBAAmB,CAAA;KAAC,CAE1E;IAEnC;;;OAGG;IACH,mBAFU,OAAO,CAEY;IAE7B;;;;OAIG;IACH,iBAFU,OAAO,CAEU;IAG/B;;;;;;;;;;;;;;;OAeG;IACH,qBAbuB,MAAM,mBACF,MAAM,sBACH,MAAM,UAClB,MAAM,aACH,MAAM,eACJ,MAAM,YACT,MAAM,cACJ,MAAM,GAAC,IAAI,mBACP,MAAM,GAAC,IAAI,aACjB,WAAS,IAAI,GACpB,OAAO,CAAC,IAAI,CAAC,CA2MzB;IAGD;;;;;;;;;OASG;IACH,0FAFa,OAAO,CAAC,IAAI,CAAC,CAkCzB;CACJ;uBAzToB,cAAc;8CAGS,gBAAgB;yBADrC,cAAc;+BAJa,gBAAgB;oCAAhB,gBAAgB"} 1 + {"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../lib/restore.js"],"names":[],"mappings":"wBACa,OAAO,iBAAiB,EAAE,SAAS;AAWhD;IAEI;;;OAGG;IACH,gCAF6B,MAAM,EA0ClC;IAvCG;;wBAEoB;IACpB,QADU,MAAM,CACU;IAE1B;;;OAGG;IACH,mBAFU,MAAM,CAE0B;IAE1C;;;;OAIG;IACH,yBAFU,IAAI,GAAC,6BAA6B,CAET;IAEnC,uBAAuB;IACvB,UADW,QAAQ,CACC;IAEpB;;;OAGG;IACH,yBAFU,IAAI,GAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,WAAW,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,cAAc,GAAC,mBAAmB,CAAA;KAAC,CAE1E;IAEnC;;;OAGG;IACH,mBAFU,OAAO,CAEY;IAE7B;;;;OAIG;IACH,iBAFU,OAAO,CAEU;IAG/B;;;;;;;;;;;;;;;OAeG;IACH,qBAbuB,MAAM,mBACF,MAAM,sBACH,MAAM,UAClB,MAAM,aACH,MAAM,eACJ,MAAM,YACT,MAAM,cACJ,MAAM,GAAC,IAAI,mBACP,MAAM,GAAC,IAAI,aACjB,WAAS,IAAI,GACpB,OAAO,CAAC,IAAI,CAAC,CA2MzB;IAGD;;;;;;;;;OASG;IACH,0FAFa,OAAO,CAAC,IAAI,CAAC,CAkCzB;CACJ;uBA7ToB,cAAc;8CAGS,gBAAgB;yBADrC,cAAc;+BAJa,gBAAgB;oCAAhB,gBAAgB"}
+2 -2
web-ui/bun.lock
··· 6 6 "dependencies": { 7 7 "@atcute/client": "^4.0.5", 8 8 "@atcute/lexicons": "^1.2.2", 9 - "@pds-moover/lexicons": "^1.0.0", 9 + "@pds-moover/lexicons": "^1.0.1", 10 10 "@pds-moover/moover": "file:../packages/moover", 11 11 }, 12 12 "devDependencies": { ··· 161 161 162 162 "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], 163 163 164 - "@pds-moover/lexicons": ["@pds-moover/lexicons@1.0.0", "", { "dependencies": { "@atproto/lexicon": "^0.5.1", "@atproto/xrpc": "^0.7.5" } }, "sha512-1/q4ZUf0PuyDTLuyuGunsBvQBo1+V8W80/QAw7VHqO6Uvu/+VjcriM2C7O4F7Q+KFX3QPFEiK0vRSyaSdgg5Zw=="], 164 + "@pds-moover/lexicons": ["@pds-moover/lexicons@1.0.1", "", { "dependencies": { "@atproto/lexicon": "^0.5.1", "@atproto/xrpc": "^0.7.5" } }, "sha512-fv5b/DtHM7FEo/JklyF9gdK0ainlb6mWjWrBe6cmSAeg9G/4O2jBlQUOqfOAICY9gOcrCpkOrk9PHgGw//JQ2A=="], 165 165 166 166 "@pds-moover/moover": ["@pds-moover/moover@file:../packages/moover", { "dependencies": { "@atcute/cbor": "^2.2.7", "@atcute/client": "^4.0.4", "@atcute/crypto": "^2.2.5", "@atcute/did-plc": "^0.1.7", "@atcute/identity-resolver": "^1.1.3", "@atcute/multibase": "^1.1.6", "@atproto/api": "^0.16.7" }, "devDependencies": { "eslint": "^9.34.0", "eslint-plugin-import": "^2.32.0" } }], 167 167
+1 -1
web-ui/package.json
··· 15 15 "dependencies": { 16 16 "@atcute/client": "^4.0.5", 17 17 "@atcute/lexicons": "^1.2.2", 18 - "@pds-moover/lexicons": "^1.0.0", 18 + "@pds-moover/lexicons": "^1.0.1", 19 19 "@pds-moover/moover": "file:../packages/moover" 20 20 }, 21 21 "devDependencies": {
+4 -1
web-ui/src/routes/backups/+page.svelte
··· 10 10 11 11 12 12 // Service instances 13 + let tempBackupService = new BackupService(`did:web:${PUBLIC_XRPC_BASE}`); 14 + tempBackupService.atCuteCredentialManager 15 + 13 16 let backupService = $state(new BackupService(`did:web:${PUBLIC_XRPC_BASE}`)); 14 17 let plcOps = $state(new PlcOps()); 15 18 ··· 166 169 <div> 167 170 <button type="submit" disabled={isLoggingIn}> 168 171 {#if isLoggingIn} 169 - <LoadingSpinner /> 172 + <LoadingSpinner/> 170 173 {/if} 171 174 Login for backups 172 175 </button>
+231
web-ui/src/routes/restore/+page.svelte
··· 1 + <script lang="ts"> 2 + import {Restore} from '@pds-moover/moover'; 3 + import MooHeader from '$lib/components/MooHeader.svelte'; 4 + import LoadingSpinner from '$lib/components/LoadingSpinner.svelte'; 5 + import {PUBLIC_XRPC_BASE} from '$env/static/public'; 6 + 7 + // Service instances 8 + let restoreService = $state(new Restore(`https://${PUBLIC_XRPC_BASE}`)); 9 + 10 + // Form inputs 11 + let currentHandle = $state(''); 12 + let rotationKey = $state(''); 13 + let newPds = $state(''); 14 + let newHandle = $state(''); 15 + let newPassword = $state(''); 16 + let newEmail = $state(''); 17 + let inviteCode = $state(''); 18 + let cid = $state(''); 19 + 20 + // Advanced options 21 + let restoreOnlyFilesFromBackup = $state(false); 22 + 23 + // UI state 24 + let error = $state<string | null>(null); 25 + let showStatusMessage = $state(false); 26 + let showAdvanced = $state(false); 27 + let done = $state(false); 28 + let statusMessageText = $state(''); 29 + let isSubmitting = $state(false); 30 + 31 + function setStatus(message: string) { 32 + console.log('Status update:', message); 33 + statusMessageText = message; 34 + showStatusMessage = true; 35 + } 36 + 37 + async function handleSubmit() { 38 + error = null; 39 + showStatusMessage = false; 40 + isSubmitting = true; 41 + 42 + try { 43 + // If set to true only restores files from backup not plc ops 44 + restoreService.RestoreFromBackup = restoreOnlyFilesFromBackup; 45 + restoreService.AccountRecovery = !restoreOnlyFilesFromBackup; 46 + 47 + // The TypeScript signature requires rotationKeyType as second parameter 48 + // Default to 'secp256k1' as mentioned in the comments 49 + await restoreService.recover( 50 + rotationKey, 51 + 'secp256k1', // rotationKeyType - defaults to secp256k1 52 + currentHandle, 53 + newPds, 54 + newHandle, 55 + newPassword, 56 + newEmail, 57 + inviteCode || null, 58 + cid || null, 59 + setStatus 60 + ); 61 + done = true; 62 + } catch (e) { 63 + console.error(e); 64 + // @ts-expect-error: Error is handled 65 + error = e.message || 'An error occurred'; 66 + } finally { 67 + isSubmitting = false; 68 + } 69 + } 70 + </script> 71 + 72 + <svelte:head> 73 + <meta property="og:description" content="Restore your ATProto account using a rotation key"/> 74 + </svelte:head> 75 + 76 + <div class="container"> 77 + <MooHeader title="Restore"/> 78 + 79 + <div class="section"> 80 + <p style="text-align: left"> 81 + Use this page to restore your AT Protocol account on a new PDS using your private rotation 82 + key. It's intended to be used in the worst case scenario, and not for normal account 83 + migrations. We do not need your password since your rotation key is what is used to recover 84 + your account. Once your account has been moved to a new PDS we will also attempt to restore 85 + your repo and blobs(pictures/videos) from our backups. 86 + </p> 87 + </div> 88 + 89 + {#if !done} 90 + <form 91 + id="restore-form" 92 + onsubmit={(e) => { 93 + e.preventDefault(); 94 + handleSubmit(); 95 + }} 96 + > 97 + <div class="form-group"> 98 + <label for="current-handle" 99 + >Your current handle or did (found in the recovery rotation-key.txt)</label 100 + > 101 + <input 102 + id="current-handle" 103 + bind:value={currentHandle} 104 + placeholder="Your current handle" 105 + required 106 + /> 107 + </div> 108 + 109 + {#if !restoreOnlyFilesFromBackup} 110 + <div class="form-group"> 111 + <label for="rotationKey">Private Rotation Key</label> 112 + <input 113 + id="rotationKey" 114 + bind:value={rotationKey} 115 + placeholder="a secp256k1 or p256 in either hex or multikey format" 116 + required={!restoreOnlyFilesFromBackup} 117 + /> 118 + </div> 119 + {/if} 120 + 121 + <div class="form-group"> 122 + <label for="newPds">New PDS</label> 123 + <input 124 + id="newPds" 125 + type="text" 126 + bind:value={newPds} 127 + placeholder="https://newpds.com" 128 + required 129 + /> 130 + </div> 131 + 132 + <div class="form-group"> 133 + <label for="newHandle">New Handle</label> 134 + <input 135 + id="newHandle" 136 + type="text" 137 + bind:value={newHandle} 138 + placeholder="you.newpds.com or thisisme.com" 139 + required 140 + /> 141 + </div> 142 + 143 + <div class="form-group"> 144 + <label for="newPassword">New Password</label> 145 + <input id="newPassword" type="password" bind:value={newPassword} required/> 146 + </div> 147 + 148 + <div class="form-group"> 149 + <label for="newEmail">New Email</label> 150 + <input 151 + id="newEmail" 152 + type="email" 153 + bind:value={newEmail} 154 + placeholder="you@example.com" 155 + required 156 + /> 157 + </div> 158 + 159 + <div class="form-group"> 160 + <label for="inviteCode">Invite code (optional)</label> 161 + <input id="inviteCode" type="text" bind:value={inviteCode} placeholder="Optional"/> 162 + </div> 163 + 164 + <div class="form-group"> 165 + <button type="button" onclick={() => (showAdvanced = !showAdvanced)}> 166 + {showAdvanced ? 'Hide advanced options' : 'Show advanced options'} 167 + </button> 168 + </div> 169 + 170 + {#if showAdvanced} 171 + <div class="advanced-options"> 172 + <div class="form-group"> 173 + <label class="moove-checkbox-label"> 174 + <input 175 + id="restoreOnlyFilesFromBackup" 176 + type="checkbox" 177 + bind:checked={restoreOnlyFilesFromBackup} 178 + /> 179 + Restore only files from backup, No PLC operations 180 + </label> 181 + </div> 182 + {#if !restoreOnlyFilesFromBackup} 183 + <div class="form-group"> 184 + <label for="cid">Cid (optional)</label> 185 + <input 186 + id="cid" 187 + type="text" 188 + bind:value={cid} 189 + placeholder="Specific PLC audit log CID to restore to (advanced)" 190 + /> 191 + <small class="help-text" 192 + >Leave empty for normal restore. IF someone besides you changed your did doc and 193 + stolen your atproto identity you have up to 72hrs to reverse that change with a valid 194 + rotation key. This input allows you to restore to the last good PLC op via it's 195 + CID.</small 196 + > 197 + </div> 198 + {/if} 199 + </div> 200 + {/if} 201 + 202 + {#if error} 203 + <div class="error-message">{error}</div> 204 + {/if} 205 + {#if showStatusMessage} 206 + <div class="status-message">{statusMessageText}</div> 207 + {/if} 208 + 209 + <div class="form-actions"> 210 + <button type="submit" disabled={isSubmitting}> 211 + {#if isSubmitting} 212 + <LoadingSpinner/> 213 + {/if} 214 + Recover and restore your account 215 + </button> 216 + </div> 217 + </form> 218 + {/if} 219 + 220 + <!-- Done --> 221 + {#if done} 222 + <div class="section"> 223 + <div class="status-message"> 224 + Congratulations! You have successfully recovered your account! Remember to use your new 225 + PDS URL under "Hosting provider" when logging in on Bluesky. Can find more detail 226 + information 227 + <a href="/info#cant-login">here.</a> 228 + </div> 229 + </div> 230 + {/if} 231 + </div>