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

Configure Feed

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

pds-moover / web-ui / src / routes / moover / +page.svelte
12 kB 267 lines
1<script lang="ts"> 2 import MooHeader from '$lib/components/MooHeader.svelte'; 3 import OgImage from '$lib/components/OgImage.svelte'; 4 import {resolve} from '$app/paths'; 5 import {Migrator} from '@pds-moover/moover'; 6 import SignThePapers from './SignThePapers.svelte'; 7 8 let formData = $state({ 9 handle: '', 10 password: '', 11 newPds: '', 12 newEmail: '', 13 newHandle: '', 14 inviteCode: null, 15 twoFactorCode: null, 16 confirmation: false, 17 // Advanced options 18 createNewAccount: true, 19 migrateRepo: true, 20 migrateBlobs: true, 21 migrateMissingBlobs: true, 22 migratePrefs: true, 23 migratePlcRecord: true, 24 }); 25 26 let migrator = $state(new Migrator()); 27 28 //UI state 29 let showTwoFactorCodeInput = $state(false); 30 let showAdvance = $state(false); 31 let showStatusMessage = $state(false); 32 let askForPlcToken = $state(false); 33 let disableSubmit = $state(false); 34 35 let errorMessage: null | string = $state(null); 36 let statusMessage: null | string = $state(null); 37 38 const updateStatusHandler = (status: string) => { 39 statusMessage = status; 40 } 41 42 async function submitMoove(event: SubmitEvent & { currentTarget: EventTarget & HTMLFormElement }) { 43 event.preventDefault(); 44 disableSubmit = true; 45 errorMessage = null; 46 showStatusMessage = false; 47 48 if (!formData.confirmation) { 49 errorMessage = 'Please confirm that you understand the risks of doing an account migration'; 50 disableSubmit = false; 51 return; 52 } 53 54 try { 55 56 if (showTwoFactorCodeInput) { 57 if (showTwoFactorCodeInput === null) { 58 errorMessage = 'Please enter the 2FA that was sent to your email.' 59 disableSubmit = false; 60 return; 61 } 62 } 63 64 // Advance options from $state 65 migrator.createNewAccount = formData.createNewAccount; 66 migrator.migrateRepo = formData.migrateRepo; 67 migrator.migrateBlobs = formData.migrateBlobs; 68 migrator.migrateMissingBlobs = formData.migrateMissingBlobs; 69 migrator.migratePrefs = formData.migratePrefs; 70 migrator.migratePlcRecord = formData.migratePlcRecord; 71 72 console.log(migrator); 73 74 updateStatusHandler('Starting migration...'); 75 showStatusMessage = true; 76 await migrator.migrate( 77 formData.handle, 78 formData.password, 79 formData.newPds, 80 formData.newEmail, 81 formData.newHandle, 82 formData.inviteCode, 83 updateStatusHandler, 84 formData.twoFactorCode, 85 ); 86 if (migrator.migratePlcRecord) { 87 //I don't think disable submit is needed, but you never know. 88 disableSubmit = false; 89 askForPlcToken = true; 90 } else { 91 updateStatusHandler('Migration of your repo is complete! But the PLC operation was not done so your old account is still the valid one.'); 92 } 93 } catch (error) { 94 disableSubmit = false; 95 console.error(error); 96 //@ts-expect-error: JS being js. doesn't like not having the type' 97 if (error.error === 'AuthFactorTokenRequired') { 98 showTwoFactorCodeInput = true; 99 } 100 //@ts-expect-error: JS being js. doesn't like not having the type' 101 errorMessage = error.message; 102 } 103 } 104</script> 105 106<svelte:head> 107 <title>PDS MOOver</title> 108 <meta property="og:description" content="ATProto account migration tool"/> 109 <OgImage/> 110</svelte:head> 111 112<div class="container"> 113 <MooHeader title="PDS MOOver"/> 114 {#if !askForPlcToken} 115 <a href={resolve('/info')}>Idk if I trust a cow to move my atproto account to a new PDS</a> 116 <br/> 117 <a href="https://blacksky.community/profile/did:plc:g7j6qok5us4hjqlwjxwrrkjm/post/3lw3hcuojck2u">Video guide for 118 joining blacksky.app</a> 119 120 <form id="moover-form" onsubmit={submitMoove}> 121 <!-- First section: Login credentials --> 122 <div class="section"> 123 <h2>Login for your current PDS</h2> 124 <div class="form-group"> 125 <label for="handle">Old Handle:</label> 126 <input type="text" id="handle" name="handle" placeholder="alice.bsky.social" required 127 bind:value={formData.handle}> 128 </div> 129 130 <div class="form-group"> 131 <label for="password">Old Password (Will also be your new password):</label> 132 <input type="password" id="password" name="password" required bind:value={formData.password}> 133 </div> 134 {#if showTwoFactorCodeInput} 135 <div class="form-group"> 136 <label for="two-factor-code">2FA from the email sent</label> 137 <input type="text" id="two-factor-code" name="twoFactorCode" 138 bind:value={formData.twoFactorCode}> 139 <div class="error-message">Enter your 2fa code here</div> 140 141 </div> 142 {/if} 143 </div> 144 145 <!-- Second section: New account details --> 146 <div class="section"> 147 <h2>Setup for the new PDS</h2> 148 <div class="form-group"> 149 <label for="new-pds">New PDS (URL):</label> 150 <input type="url" id="new-pds" name="newPds" placeholder="https://coolnewpds.com" 151 required bind:value={formData.newPds}> 152 </div> 153 154 <div class="form-group"> 155 <label for="new-email">New Email:</label> 156 <input type="email" id="new-email" name="newEmail" placeholder="CanBeSameEmailAsTheOldPds@email.com" 157 required bind:value={formData.newEmail}> 158 </div> 159 160 <div class="form-group"> 161 <label for="new-handle">New Handle:</label> 162 <input type="text" id="new-handle" name="newHandle" 163 placeholder="username.newpds.com or mycooldomain.com" required 164 bind:value={formData.newHandle}> 165 </div> 166 167 <div class="form-group"> 168 <label for="invite-code">Invite Code:</label> 169 <input type="text" id="invite-code" name="inviteCode" 170 placeholder="Invite code from your new PDS (Leave blank if you don't have one)" 171 bind:value={formData.inviteCode}> 172 </div> 173 </div> 174 175 <div class="form-group"> 176 <button type="button" onclick={() => showAdvance = !showAdvance} id="advance" name="advance">Advance 177 Options 178 </button> 179 </div> 180 {#if showAdvance} 181 <div class="section" style="padding-bottom: 10px; text-align: left"> 182 <h3>Pick and choose which actions to run</h3> 183 <p>Useful if a migration failed and you want to have a bit more manual control</p> 184 <div class="form-control"> 185 <label class="moove-checkbox-label"> 186 <input type="checkbox" id="createNewAccount" name="createNewAccount" 187 bind:checked={formData.createNewAccount}> 188 Create a New Account on the New PDS 189 </label> 190 </div> 191 <div class="form-control"> 192 <label class="moove-checkbox-label"> 193 <input bind:checked={formData.migrateRepo} type="checkbox" id="migrateRepo" 194 name="migrateRepo"> 195 Migrate Repo 196 </label> 197 </div> 198 <div class="form-control"> 199 <label class="moove-checkbox-label"> 200 <input bind:checked={formData.migrateBlobs} type="checkbox" id="migrateBlobs" 201 name="migrateBlobs"> 202 Migrate Blobs 203 </label> 204 </div> 205 <div class="form-control"> 206 <label class="moove-checkbox-label"> 207 <input bind:checked={formData.migrateMissingBlobs} type="checkbox" id="migrateMissingBlobs" 208 name="migrateMissingBlobs"> 209 Migrate Missing Blobs 210 </label> 211 </div> 212 <div class="form-control"> 213 <label class="moove-checkbox-label"> 214 <input bind:checked={formData.migratePrefs} type="checkbox" id="migratePrefs" 215 name="migratePrefs"> 216 Migrate Prefs 217 </label> 218 </div> 219 <div class="form-control"> 220 <label class="moove-checkbox-label"> 221 <input bind:checked={formData.migratePlcRecord} type="checkbox" id="migratePlcRecord" 222 name="migratePlcRecord"> 223 Migrate PLC Record 224 </label> 225 </div> 226 227 </div> 228 {/if} 229 230 <p style="text-align: left">There are some risks that come with doing an account migration. 231 (Can view them 232 <a href="https://github.com/bluesky-social/pds/blob/main/ACCOUNT_MIGRATION.md#%EF%B8%8F-warning-%EF%B8%8F-%EF%B8%8F">here</a>) 233 and that the creator or host of this migration tool is not liable and will not be able to help you in 234 the 235 event something goes wrong. I also have read over the <a href={resolve('/info')}>extended information 236 from 237 PDS MOOver 238 about account 239 migrations.</a> 240 </p> 241 <div class="form-group"> 242 <label for="confirmation" class="moove-checkbox-label"> 243 <input bind:checked={formData.confirmation} type="checkbox" id="confirmation" name="confirmation" 244 required> 245 <span>I understand</span> 246 </label> 247 </div> 248 {#if errorMessage !== null} 249 <div class="error-message">{errorMessage}</div> 250 {/if} 251 252 {#if showStatusMessage} 253 <div id="warning">*Please make sure to stay on this page during the MOOve for the 254 best result 255 </div> 256 <div id="status-message" class="status-message">{statusMessage}</div> 257 {/if} 258 259 <div> 260 <button disabled={disableSubmit} type="submit">MOOve</button> 261 </div> 262 </form> 263 264 {:else} 265 <SignThePapers migrator={migrator} newHandle={formData.newHandle}/> 266 {/if} 267</div>