diff --git a/web/src/lib/api/settings.ts b/web/src/lib/api/settings.ts new file mode 100644 --- /dev/null +++ b/web/src/lib/api/settings.ts @@ -0,0 +1,78 @@ +import { ok } from "@atcute/client"; +import { now as tidNow } from "@atcute/tid"; +import { mainSchema as createRecordSchema } from "@atcute/atproto/types/repo/createRecord"; +import { mainSchema as deleteRecordSchema } from "@atcute/atproto/types/repo/deleteRecord"; +import type { Nsid, RecordKey } from "@atcute/lexicons/syntax"; +import type { OAuthUserAgent } from "@atcute/oauth-browser-client"; +import { createClient } from "$lib/auth/agent"; +import { jsonGet } from "./_request"; +import type { BobbinContext, XrpcRequestInit } from "./client"; +import { rkeyFromUri } from "./uri"; +import type * as ShTangledPublicKey from "./lexicons/types/sh/tangled/publicKey"; + +export type PublicKeyRecord = ShTangledPublicKey.Main; + +const PUBLIC_KEY_COLLECTION = "sh.tangled.publicKey" as Nsid; + +export interface ListedRecord { + uri: string; + rkey: string; + value: V; +} + +interface ListResponse { + cursor?: string; + items: { uri: string; cid?: string; value: unknown }[]; +} + +const listRecords = async ( + ctx: BobbinContext, + nsid: string, + did: string, + init?: XrpcRequestInit +): Promise[]> => { + const res = await jsonGet(ctx, nsid, { subject: did }, init); + return res.items.map((item) => ({ + uri: item.uri, + rkey: rkeyFromUri(item.uri), + value: item.value as V + })); +}; + +export const listPubKeys = (ctx: BobbinContext, did: string, init?: XrpcRequestInit) => + listRecords(ctx, "sh.tangled.publicKey.listKeys", did, init); + +export const createPubKey = async ( + agent: OAuthUserAgent, + name: string, + key: string +): Promise => { + const rpc = createClient(agent); + // the client mints the rkey (a TID) rather than letting the PDS assign one. + const rkey = tidNow(); + await ok( + rpc.call(createRecordSchema, { + input: { + repo: agent.sub, + collection: PUBLIC_KEY_COLLECTION, + rkey: rkey as RecordKey, + record: { + $type: "sh.tangled.publicKey", + name, + key, + createdAt: new Date().toISOString() + } + } + }) + ); + return rkey; +}; + +export const deletePubKey = async (agent: OAuthUserAgent, rkey: string): Promise => { + const rpc = createClient(agent); + await ok( + rpc.call(deleteRecordSchema, { + input: { repo: agent.sub, collection: PUBLIC_KEY_COLLECTION, rkey: rkey as RecordKey } + }) + ); +}; diff --git a/web/src/routes/settings/spindles/+page.svelte b/web/src/routes/settings/spindles/+page.svelte new file mode 100644 --- /dev/null +++ b/web/src/routes/settings/spindles/+page.svelte @@ -0,0 +1,5 @@ + + +