mirror your GitHub repos to tangled.org automatically
1

Configure Feed

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

1import type { H3Event } from 'h3' 2import { sessionConfig } from './server-session' 3 4/** 5 * Short-lived sealed cookie proving the current browser completed GitHub 6 * user-OAuth and was confirmed as an administrator of a specific installation. 7 * 8 * The atproto callback checks this before binding a DID to an installation, so 9 * a connecting user can't claim an installation they don't actually control by 10 * crafting `/connect?installation_id=<victim>`. Reuses the session password 11 * for sealing; a distinct cookie name and a 15-minute TTL keep it scoped to a 12 * single connect flow. 13 */ 14interface InstallOwnershipData { 15 installationId: number 16 verifiedAt: number 17} 18 19const COOKIE_NAME = 'synchub-install-ownership' 20const TTL_SECONDS = 15 * 60 21 22function ownershipConfig() { 23 return { ...sessionConfig(), name: COOKIE_NAME, maxAge: TTL_SECONDS } 24} 25 26export async function markInstallOwned(event: H3Event, installationId: number): Promise<void> { 27 const session = await useSession<InstallOwnershipData>(event, ownershipConfig()) 28 await session.update({ installationId, verifiedAt: Date.now() }) 29} 30 31/** 32 * Return true if the current browser proved ownership of `installationId` 33 * within the TTL. Does not clear the cookie; the caller clears it after a 34 * successful bind so it can't be replayed. 35 */ 36export async function hasVerifiedInstall(event: H3Event, installationId: number): Promise<boolean> { 37 const session = await useSession<InstallOwnershipData>(event, ownershipConfig()) 38 const { installationId: owned, verifiedAt } = session.data 39 if (typeof owned !== 'number' || typeof verifiedAt !== 'number') return false 40 if (owned !== installationId) return false 41 if (Date.now() - verifiedAt > TTL_SECONDS * 1000) return false 42 return true 43} 44 45export async function clearInstallOwnership(event: H3Event): Promise<void> { 46 const session = await useSession<InstallOwnershipData>(event, ownershipConfig()) 47 await session.clear() 48}