Something went wrong. Try again.
Client side atproto account migrator in your web browser, along with services for backups and adversarial migrations. pdsmoover.com
pds atproto migrations moo cow
Something went wrong. Try again.
5.6 kB · 141 lines
Svelte
at oauth
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142<script lang="ts"> import {auth, consumeJustSignedIn, signIn, signOut} from '$lib/oauth/session.svelte'; import AccountSummary from '$lib/components/AccountSummary.svelte'; import Button from '$lib/components/ui/Button.svelte'; import Disclosure from '$lib/components/ui/Disclosure.svelte'; import ErrorMessage from '$lib/components/ui/ErrorMessage.svelte'; import HandleTypeaheadField from '$lib/components/ui/HandleTypeaheadField.svelte'; import StatusMessage from '$lib/components/ui/StatusMessage.svelte'; import type {Snippet} from 'svelte';
interface Props { /** The OAuth scope this page needs on the current account */ scope: string; /** In-app path to come back to after the PDS redirects to /oauth/callback */ returnTo: string; title?: string; /** Set when the restored session lacks a permission this page needs */ needsMorePermissions?: boolean; /** Fired when the user confirms they want to continue with the signed-in account */ onContinue?: () => void; /** Optional less-common permission controls, tucked into an "Advanced permissions" disclosure */ advancedPermissions?: Snippet; }
let { scope, returnTo, title = 'Sign in with your current account', needsMorePermissions = false, onContinue, advancedPermissions, }: Props = $props();
let identifier = $state(''); let busy = $state(false); let errorMessage = $state<string | null>(null);
// A sign-in the user just approved for this page skips the confirmation: advancing the parent // to its next step is the same behaviour the MOOver wizard uses. let autoContinued = false; $effect(() => { if (autoContinued || !onContinue) return; if (!auth.session || needsMorePermissions) return; if (!consumeJustSignedIn(returnTo)) return; autoContinued = true; onContinue(); });
async function startSignIn(who: string) { busy = true; errorMessage = null; try { await signIn(who, {scope, returnTo}); } catch (error) { console.error(error); errorMessage = error instanceof Error ? error.message : 'Could not start sign in'; busy = false; } }
async function submit(event: SubmitEvent) { event.preventDefault(); await startSignIn(identifier); }
async function handleSignOut() { busy = true; await signOut(); busy = false; }</script>
{#snippet advancedSection()} {#if advancedPermissions} <Disclosure label="Advanced permissions"> {@render advancedPermissions()} </Disclosure> {/if}{/snippet}
<div class="mt-7.5 text-left"> {#if auth.status === 'idle' || auth.status === 'loading'} <h2>{title}</h2> <StatusMessage role="status" spinner> Checking for a signed-in account... </StatusMessage> {:else if auth.session} <!-- Step 1 of the wizard: confirm which account the tool acts on before showing its content. --> <AccountSummary/> <div class="mt-3"> {#if needsMorePermissions} <p class="font-bold"> This page needs permissions your current sign-in did not grant. Sign in again so your PDS can ask you for them. </p> <div class="mt-3"> <Button id="sign-in-again" {busy} onclick={() => startSignIn(auth.session?.did ?? identifier)}> Sign in again </Button> </div> {@render advancedSection()} {:else} <p class="text-[0.9em] opacity-80"> Continue with this account to use the tool, or sign out to use a different one. </p> <div class="mt-3 flex flex-wrap gap-2"> <Button id="continue" {busy} onclick={() => onContinue?.()}> Continue with this account </Button> <Button id="sign-out" variant="secondary" {busy} onclick={handleSignOut}> Sign out </Button> </div> {@render advancedSection()} {/if} </div> {:else} <h2>{title}</h2> {#if auth.status === 'error' && auth.error} <ErrorMessage> Could not restore your previous sign-in: {auth.error} </ErrorMessage> <p class="text-[0.9em] opacity-80">Signing in below creates a fresh session and fixes this.</p> {/if} <form onsubmit={submit}> <p>You will be sent to your PDS to approve the permissions this page needs. Your password is only ever typed into your own PDS.</p> <HandleTypeaheadField id="sign-in-handle" label="Current handle (or DID)" name="handle" placeholder="alice.bsky.social" required autocomplete="username" bind:value={identifier}/> {#if errorMessage} <ErrorMessage>{errorMessage}</ErrorMessage> {/if} <div class="mb-3.75 text-left"> <Button id="sign-in" type="submit" {busy}> Sign in with your PDS </Button> </div> {@render advancedSection()} </form> {/if}</div>