diff --git a/bun.lockb b/bun.lockb index bb99019d49af2574ba5eed9fb0dbd8d0dea90d13..4232f44825925efb76bb8d892028ad06697a9b4a 100755 GIT binary patch delta 23349 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 { - const sid = event.cookies.get("sid"); - - // if there is a session cookie - if (sid) { - // if a user is already authed, skip reauthing - if (event.locals.user) { return resolve(event); } - - // decrypt session cookie - const decoded = decodeBase64urlIgnorePadding(sid); - const key = decodeBase64(ENCRYPTION_PASSWORD); - const decrypted = await decryptToString(key, decoded); - - // get oauth session from client using decrypted cookie - const oauthSession = await atclient.restore(decrypted); - - // set the authed agent - const authedAgent = new Agent(oauthSession); - event.locals.authedAgent = authedAgent; - - // set the authed user with decrypted session DID - const user = await authedAgent.getProfile({ actor: decrypted }); - event.locals.user = user.data; - } - - return resolve(event); -} diff --git a/src/lib/atproto.ts b/src/lib/atproto.ts deleted file mode 100644 index c381e0f..0000000 --- a/src/lib/atproto.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { db } from "./server/db"; -import { NodeOAuthClient } from "@atproto/oauth-client-node"; -import { AuthSessionStore, AuthStateStore } from "./stores"; - -import { dev } from "$app/environment"; - -const publicUrl = "https://potatonet.app" -// localhost resolves to either 127.0.0.1 or [::1] (if ipv6) -const url = dev ? "http://[::1]:5173" : publicUrl; - -export const atclient = new NodeOAuthClient({ - stateStore: new AuthStateStore(db), - sessionStore: new AuthSessionStore(db), - clientMetadata: { - client_name: "potatonet-app", - client_id: !dev ? `${publicUrl}/client-metadata.json` - : `http://localhost?redirect_uri=${ - encodeURIComponent(`${url}/oauth/callback`) - }&scope=${ - encodeURIComponent(`atproto transition:generic`) - }`, - client_uri: url, - redirect_uris: [`${url}/oauth/callback`], - scope: "atproto transition:generic", - grant_types: ["authorization_code", "refresh_token"], - application_type: "web", - token_endpoint_auth_method: "none", - dpop_bound_access_tokens: true - } -}); diff --git a/src/lib/components/BookmarkCard.svelte b/src/lib/components/BookmarkCard.svelte deleted file mode 100644 index 33c5c30..0000000 --- a/src/lib/components/BookmarkCard.svelte +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - diff --git a/src/lib/components/TagPill.svelte b/src/lib/components/TagPill.svelte deleted file mode 100644 index 0454b29..0000000 --- a/src/lib/components/TagPill.svelte +++ /dev/null @@ -1,39 +0,0 @@ - - -
- {#if showDeleteButton && variant !== "menu"} - - {/if} - - {#if showDeleteButton} - - {/if} -
diff --git a/src/lib/server/api.ts b/src/lib/server/api.ts deleted file mode 100644 index 95efe86..0000000 --- a/src/lib/server/api.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { SLICES_BEARER_TOKEN, SLICES_NETWORK_ACCESS_TOKEN } from "$env/static/private"; -import type { LexiconCommunityBookmark, SliceItem, SliceList } from "$lib/utils"; - -const SLICES_NETWORK_SLICE_URI = "at://did:plc:gotnvwkr56ibs33l4hwgfoet/network.slices.slice/3m26tswgbi42i" - -const baseUrl = "https://slices-api.fly.dev/xrpc/"; - -type GetListProps = { - limit?: number; // default: 50, max: 100 - cursor?: string | null; - where?: { - [key: string]: { eq?: string, contains?: string, in?: string[] } - }; - sortBy?: { field: string, direction: "desc" | "asc" }[] -}; - -export class SlicesAPI { - - collection: string; - sliceUri: string; - - constructor({ collection, sliceUri }: { collection: string, sliceUri : string }) { - this.collection = collection; - this.sliceUri = sliceUri; - } - - /** - async getRecord({ uri }: { uri: string }) { - const response = await fetch(`${baseUrl}${this.collection}.getRecord?${searchParams.toString()}`); - return await response.json() as SliceItem; - } - **/ - - async getList(body: GetListProps) { - const response = await fetch(`${baseUrl}${this.collection}.getRecords`, { - method: "POST", - headers: { - // "Accept": "*/*", - "Content-Type": "application/json", - // "Authorization": `Bearer ${SLICES_BEARER_TOKEN}` - }, - body: JSON.stringify({ ...body, slice: SLICES_NETWORK_SLICE_URI }) - }); - const data = await response.json() as SliceList; - for (const d of data.records) { - console.log(d); - } - console.log(data.cursor); - return data; - } -} - -export const LexiconBookmarkSlicesAPI = new SlicesAPI({ - collection: "community.lexicon.bookmarks.bookmark", - sliceUri: SLICES_NETWORK_SLICE_URI -}); diff --git a/src/lib/server/db/index.ts b/src/lib/server/db/index.ts deleted file mode 100644 index 5e551f3..0000000 --- a/src/lib/server/db/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { drizzle } from 'drizzle-orm/postgres-js'; -import postgres from 'postgres'; -import { env } from '$env/dynamic/private'; -import * as schema from "./schema"; - -if (!env.DATABASE_URL) throw new Error('DATABASE_URL is not set'); -const client = postgres(env.DATABASE_URL); - -// add schema -export const db = drizzle(client, { schema }); diff --git a/src/lib/server/db/schema.ts b/src/lib/server/db/schema.ts deleted file mode 100644 index b41ebf8..0000000 --- a/src/lib/server/db/schema.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { pgTable, text, json } from 'drizzle-orm/pg-core'; - -export const AuthState = pgTable('auth_state', { - key: text('key').primaryKey().unique(), - state: json('state').notNull() -}); - -export const AuthSession = pgTable('auth_session', { - key: text('key').primaryKey().unique(), - session: json('session').notNull() -}); diff --git a/src/lib/server/encryption.ts b/src/lib/server/encryption.ts deleted file mode 100644 index aafb4d4..0000000 --- a/src/lib/server/encryption.ts +++ /dev/null @@ -1,49 +0,0 @@ -// Code by @pilcrowonpaper on GitHub: https://gist.github.com/pilcrowonpaper/353318556029221c8e25f451b91e5f76 -// AES128 with the Web Crypto API. -async function encrypt(key: Uint8Array, data: Uint8Array): Promise { - const iv = new Uint8Array(16); - crypto.getRandomValues(iv); - const cryptoKey = await crypto.subtle.importKey("raw", key, "AES-GCM", false, ["encrypt"]); - const cipher = await crypto.subtle.encrypt( - { - name: "AES-GCM", - iv, - tagLength: 128 - }, - cryptoKey, - data - ); - const encrypted = new Uint8Array(iv.byteLength + cipher.byteLength); - encrypted.set(iv); - encrypted.set(new Uint8Array(cipher), iv.byteLength); - return encrypted; -} - -export async function encryptString(key: Uint8Array, data: string): Promise { - const encoded = new TextEncoder().encode(data); - const encrypted = await encrypt(key, encoded); - return encrypted; -} - -async function decrypt(key: Uint8Array, encrypted: Uint8Array): Promise { - if (encrypted.length < 16) { - throw new Error("Invalid data"); - } - const cryptoKey = await crypto.subtle.importKey("raw", key, "AES-GCM", false, ["decrypt"]); - const decrypted = await crypto.subtle.decrypt( - { - name: "AES-GCM", - iv: encrypted.slice(0, 16), - tagLength: 128 - }, - cryptoKey, - encrypted.slice(16) - ); - return new Uint8Array(decrypted); -} - -export async function decryptToString(key: Uint8Array, data: Uint8Array): Promise { - const decrypted = await decrypt(key, data); - const decoded = new TextDecoder().decode(decrypted); - return decoded; -} diff --git a/src/lib/stores.ts b/src/lib/stores.ts deleted file mode 100644 index 59f6b15..0000000 --- a/src/lib/stores.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { eq } from "drizzle-orm"; -import { db as database } from "./server/db"; -import * as schema from "./server/db/schema"; -import type { NodeSavedSession, NodeSavedSessionStore, NodeSavedState, NodeSavedStateStore } from "@atproto/oauth-client-node"; - -// can be implemented with your preferred DB and ORM -// both stores are the same, only different is 'state' and 'session' - -export class AuthStateStore implements NodeSavedStateStore { - constructor(private db: typeof database) {} - - async get(key: string): Promise { - const result = await this.db.query.AuthState.findFirst({ - where: eq(schema.AuthState.key, key) - }); - - if (!result) return; - - return result.state as NodeSavedState; - } - - async set(key: string, val: NodeSavedState) { - await this.db.insert(schema.AuthState) - .values({ key, state: val }) - .onConflictDoUpdate({ - target: schema.AuthState.key, - set: { state: val } - }); - } - - async del(key: string) { - await this.db.delete(schema.AuthState) - .where(eq(schema.AuthState.key, key)); - } -} - -export class AuthSessionStore implements NodeSavedSessionStore { - constructor(private db: typeof database) {} - - async get(key: string): Promise { - const result = await this.db.query.AuthSession.findFirst({ - where: eq(schema.AuthSession.key, key) - }); - - if (!result) return; - return result.session as NodeSavedSession; - } - - async set(key: string, val: NodeSavedSession) { - await this.db.insert(schema.AuthSession) - .values({ key, session: val }) - .onConflictDoUpdate({ - target: schema.AuthSession.key, - set: { session: val } - }); - } - - async del(key: string) { - await this.db.delete(schema.AuthSession) - .where(eq(schema.AuthSession.key, key)); - } -} - diff --git a/src/lib/utils.ts b/src/lib/utils.ts index dab899e..88bb6ae 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,36 +1,4 @@ // --- UTILITIES --- -export type CommonSliceFields = { - indexedAt: string; - cid: string; - uri: string; - collection: string; -} - -export type LexiconCommunityBookmark = { - $type: "community.lexicon.bookmarks.bookmark"; - subject: string; - createdAt: string; - tags?: string[]; - $enriched?: { - description: string; - favicon: string; - title: string; - } -}; - -export type LexiconCommunityLike = { - $type: "community.lexicon.interaction.like"; - subject: string; - createdAt: string; -} - -export type SliceItem = CommonSliceFields & { value: T }; - -export type SliceList = { - cursor: string; - records: (CommonSliceFields & { did: string, value: T })[]; -} - export function parseAtUri(uri: string) { const regex = /at:\/\/(?did.*)\/(?.*)\/(?.*)/; const groups = regex.exec(uri)?.groups; @@ -42,7 +10,7 @@ export function parseAtUri(uri: string) { } export async function resolveHandle(handle: string) { - const result = await fetch(`https://slingshot.microcosm.blue/xrpc/com.atproto.identity.resolveHandle?handle=${handle}`) + const result = await fetch(`https://slingshot.microcosm.blue/xrpc/com.bad-example.identity.resolveMiniDoc?identifier=${encodeURIComponent(handle)}`) const info = await result.json(); - return info.did; + return info; } diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts deleted file mode 100644 index 97b521c..0000000 --- a/src/routes/+layout.server.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { ServerLoadEvent } from "@sveltejs/kit"; - -export async function load({ locals }: ServerLoadEvent) { - // have user available throughout the app via LayoutData - return !locals.user ? undefined : { user: { - did: locals.user.did, - handle: locals.user.handle - }}; -} diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index c2a97f9..2119b80 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,11 +1,24 @@ - -
-

Explore

-
- - - - - - - - - - {#if data.user} - - {/if} - - -
- -{#if exploreBookmarksQuery.isPending} -

Loading...

-{:else if exploreBookmarksQuery.isError} -

Error

-{:else if exploreBookmarksQuery.isSuccess} -
- {#if bookmarks} - {@const pagedBookmarks = bookmarks.slice(bookmarkPage*50)} - {#each pagedBookmarks as info} - {@const bookmark = info.bookmark} - {#if bookmark.subject.includes(query)} - {#if (bookmark.tags && bookmark.tags.length > 0 - && bookmark.tags.some(t => filterTags.length > 0 ? filterTags.includes(t.toLowerCase()) : true) - ) - || (bookmark.tags && bookmark.tags.length === 0 && filterTags.length === 0)} - - {/if} - {/if} - {/each} - {/if} -
-{/if} diff --git a/src/routes/[handle]/bookmarks/+page.svelte b/src/routes/[handle]/bookmarks/+page.svelte index 21d4571..0fbba99 100644 --- a/src/routes/[handle]/bookmarks/+page.svelte +++ b/src/routes/[handle]/bookmarks/+page.svelte @@ -1,96 +1,2 @@ - -
-

Bookmarks by {page.params.handle}

-
- - - - - - - - - - {#if data.user} - - {/if} - - -
- -{#if userBookmarksQuery.isPending} -

Loading...

-{:else if userBookmarksQuery.isError} -

Error

-{:else if userBookmarksQuery.isSuccess} -
- {#if bookmarks} - {@const pagedBookmarks = bookmarks.slice(bookmarkPage*50)} - {#each pagedBookmarks as info} - {@const bookmark = info.bookmark} - {#if bookmark.subject.includes(query)} - {#if (bookmark.tags && bookmark.tags.length > 0 - && bookmark.tags.some(t => filterTags.length > 0 ? filterTags.includes(t.toLowerCase()) : true) - ) - || (bookmark.tags && bookmark.tags.length === 0 && filterTags.length === 0)} - - {/if} - {/if} - {/each} - {/if} -
-{/if} diff --git a/src/routes/api/bookmarks/data.remote.ts b/src/routes/api/bookmarks/data.remote.ts deleted file mode 100644 index 1cf21ac..0000000 --- a/src/routes/api/bookmarks/data.remote.ts +++ /dev/null @@ -1,41 +0,0 @@ -import * as v from "valibot"; -import { query } from "$app/server" -import { LexiconBookmarkSlicesAPI } from "$lib/server/api" - -const GetUserBookmarksValidator = v.object({ - handle: v.string(), - cursor: v.optional(v.string()) -}); - -export const getUserBookmarks = query(GetUserBookmarksValidator, async ({ handle, cursor }) => { - const result = await fetch(`https://slingshot.microcosm.blue/xrpc/com.atproto.identity.resolveHandle?handle=${handle}`) - const info = await result.json(); - - if (!info) { throw Error(); } - - const data = await LexiconBookmarkSlicesAPI.getList({ - cursor: !cursor ? null : cursor, - where: { - did: { eq: info.did } - } - }); - - console.log(info); - - return { cursor: data.cursor, list: data.records.map((r) => { - return { did: r.did, bookmark: r.value } - })}; -}); - - -const GetAllBookmarksValidator = v.object({ - cursor: v.optional(v.string()) -}); - -export const getAllBookmarks = query(GetAllBookmarksValidator, async ({ cursor }) => { - const data = await LexiconBookmarkSlicesAPI.getList({ cursor }); - - return { cursor: data.cursor, list: data.records.map((r) => { - return { did: r.did, bookmark: r.value } - })}; -}); diff --git a/src/routes/api/metadata.remote.ts b/src/routes/api/metadata.remote.ts deleted file mode 100644 index 80742d6..0000000 --- a/src/routes/api/metadata.remote.ts +++ /dev/null @@ -1,11 +0,0 @@ -import * as v from "valibot"; -import ogs from "open-graph-scraper"; -import { query } from "$app/server"; -import { error } from "@sveltejs/kit"; - -export const getMetadata = query(v.string(), async (url) => { - if (url === "/") { return error(401); } - const response = await ogs({ url }); - if (response.error) { return error(404); } - return response.result; -}); diff --git a/src/routes/client-metadata.json/+server.ts b/src/routes/client-metadata.json/+server.ts deleted file mode 100644 index 61620b6..0000000 --- a/src/routes/client-metadata.json/+server.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { atclient } from "$lib/atproto"; -import { json } from "@sveltejs/kit"; - -export async function GET() { - return json(atclient.clientMetadata); -} diff --git a/src/routes/oauth/callback/+server.ts b/src/routes/oauth/callback/+server.ts deleted file mode 100644 index e5c180c..0000000 --- a/src/routes/oauth/callback/+server.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { atclient } from "$lib/atproto"; -import { encryptString } from "$lib/server/encryption"; -import { decodeBase64, encodeBase64urlNoPadding } from "@oslojs/encoding"; - -import { error, redirect } from "@sveltejs/kit"; -import type { RequestEvent } from "@sveltejs/kit"; -import { ENCRYPTION_PASSWORD } from "$env/static/private"; - -// called on after authorizing OAuth -export async function GET({ request, cookies }: RequestEvent) { - // get parameters set by the callback - const params = new URLSearchParams(request.url.split("?")[1]); - - try { - const { session } = await atclient.callback(params); - const key = decodeBase64(ENCRYPTION_PASSWORD); - - // encrypt the user DID - const encrypted = await encryptString(key, session.did); - const encoded = encodeBase64urlNoPadding(encrypted); - - // set encoded session DID as cookies for auth - cookies.set("sid", encoded, { - path: "/", - maxAge: 60 * 60, - httpOnly: true, - sameSite: "lax" - }); - } catch (err) { - error(500, { message: (err as Error).message }); - } - - redirect(301, `/`); -}