the statusphere demo reworked into a vite/react app in a monorepo

Fold src/auth/session into src/routes

+36 -64
-61
src/auth/session.ts
··· 1 - import assert from 'node:assert' 2 - import type { IncomingMessage, ServerResponse } from 'node:http' 3 - import { getIronSession } from 'iron-session' 4 - import { env } from '#/lib/env' 5 - import { AppContext } from '#/index' 6 - 7 - export type Session = { did: string } 8 - 9 - export async function createSession( 10 - req: IncomingMessage, 11 - res: ServerResponse<IncomingMessage>, 12 - did: string 13 - ) { 14 - const session = await getSessionRaw(req, res) 15 - assert(!session.did, 'session already exists') 16 - session.did = did 17 - await session.save() 18 - return { did: session.did } 19 - } 20 - 21 - export async function destroySession( 22 - req: IncomingMessage, 23 - res: ServerResponse<IncomingMessage> 24 - ) { 25 - const session = await getSessionRaw(req, res) 26 - await session.destroy() 27 - return null 28 - } 29 - 30 - export async function getSession( 31 - req: IncomingMessage, 32 - res: ServerResponse<IncomingMessage> 33 - ) { 34 - const session = await getSessionRaw(req, res) 35 - if (!session.did) return null 36 - return { did: session.did } 37 - } 38 - 39 - export async function getSessionAgent( 40 - req: IncomingMessage, 41 - res: ServerResponse<IncomingMessage>, 42 - ctx: AppContext 43 - ) { 44 - const session = await getSessionRaw(req, res) 45 - if (!session.did) return null 46 - return await ctx.oauthClient.restore(session.did).catch(async (err) => { 47 - ctx.logger.warn({ err }, 'oauth restore failed') 48 - await destroySession(req, res) 49 - return null 50 - }) 51 - } 52 - 53 - async function getSessionRaw( 54 - req: IncomingMessage, 55 - res: ServerResponse<IncomingMessage> 56 - ) { 57 - return await getIronSession<Session>(req, res, { 58 - cookieName: 'sid', 59 - password: env.COOKIE_SECRET, 60 - }) 61 - }
+36 -3
src/routes.ts
··· 1 + import assert from 'node:assert' 1 2 import path from 'node:path' 3 + import type { IncomingMessage, ServerResponse } from 'node:http' 2 4 import { OAuthResolverError } from '@atproto/oauth-client-node' 3 5 import { isValidHandle } from '@atproto/syntax' 4 6 import express from 'express' 5 - import { createSession, destroySession, getSessionAgent } from '#/auth/session' 7 + import { getIronSession } from 'iron-session' 6 8 import type { AppContext } from '#/index' 7 9 import { home } from '#/pages/home' 8 10 import { login } from '#/pages/login' 11 + import { env } from '#/lib/env' 9 12 import { page } from '#/lib/view' 10 13 import * as Status from '#/lexicon/types/com/example/status' 11 14 15 + type Session = { did: string } 16 + 12 17 // Helper function for defining routes 13 18 const handler = 14 19 (fn: express.Handler) => ··· 24 29 } 25 30 } 26 31 32 + // Helper function to get the Atproto Agent for the active session 33 + async function getSessionAgent( 34 + req: IncomingMessage, 35 + res: ServerResponse<IncomingMessage>, 36 + ctx: AppContext 37 + ) { 38 + const session = await getIronSession<Session>(req, res, { 39 + cookieName: 'sid', 40 + password: env.COOKIE_SECRET, 41 + }) 42 + if (!session.did) return null 43 + return await ctx.oauthClient.restore(session.did).catch(async (err) => { 44 + ctx.logger.warn({ err }, 'oauth restore failed') 45 + await session.destroy() 46 + return null 47 + }) 48 + } 49 + 27 50 export const createRouter = (ctx: AppContext) => { 28 51 const router = express.Router() 29 52 ··· 45 68 const params = new URLSearchParams(req.originalUrl.split('?')[1]) 46 69 try { 47 70 const { agent } = await ctx.oauthClient.callback(params) 48 - await createSession(req, res, agent.accountDid) 71 + const session = await getIronSession<Session>(req, res, { 72 + cookieName: 'sid', 73 + password: env.COOKIE_SECRET, 74 + }) 75 + assert(!session.did, 'session already exists') 76 + session.did = agent.accountDid 77 + await session.save() 49 78 } catch (err) { 50 79 ctx.logger.error({ err }, 'oauth callback failed') 51 80 return res.redirect('/?error') ··· 96 125 router.post( 97 126 '/logout', 98 127 handler(async (req, res) => { 99 - await destroySession(req, res) 128 + const session = await getIronSession<Session>(req, res, { 129 + cookieName: 'sid', 130 + password: env.COOKIE_SECRET, 131 + }) 132 + await session.destroy() 100 133 return res.redirect('/') 101 134 }) 102 135 )