···
import { handler } from '#/lib/http'
import { ifString } from '#/lib/util'
import { page } from '#/lib/view'
20
-
import { home, STATUS_OPTIONS } from '#/pages/home'
20
+
import { home } from '#/pages/home'
import { login } from '#/pages/login'
23
+
const MAX_AGE = env.NODE_ENV === 'production' ? 60 : 0
type Session = { did?: string }
···
46
-
export function createRouter(ctx: AppContext): RequestListener {
48
+
export const createRouter = (ctx: AppContext): RequestListener => {
50
-
router.use('/public', express.static(path.join(__dirname, 'pages', 'public')))
54
+
express.static(path.join(__dirname, 'pages', 'public'), {
55
+
maxAge: MAX_AGE * 1000,
'/oauth-client-metadata.json',
handler((req: Request, res: Response) => {
63
+
res.setHeader('cache-control', `max-age=${MAX_AGE}, public`)
res.json(ctx.oauthClient.clientMetadata)
···
'/.well-known/jwks.json',
handler((req: Request, res: Response) => {
72
+
res.setHeader('cache-control', `max-age=${MAX_AGE}, public`)
res.json(ctx.oauthClient.jwks)
···
handler(async (req: Request, res: Response) => {
81
+
res.setHeader('cache-control', 'no-store')
const params = new URLSearchParams(req.originalUrl.split('?')[1])
// Load the session cookie
···
handler(async (req: Request, res: Response) => {
119
+
res.setHeader('cache-control', `max-age=${MAX_AGE}, public`)
return res.type('html').send(page(login({})))
···
handler(async (req: Request, res: Response) => {
130
+
res.setHeader('cache-control', 'no-store')
const input = ifString(req.body.input)
return res.type('html').send(page(login({ error: 'invalid input' })))
139
+
// @NOTE "input" can be a handle, a DID or a service URL (PDS).
141
+
// Initiate the OAuth flow
143
+
const url = await ctx.oauthClient.authorize(input, {
144
+
scope: 'atproto transition:generic',
146
+
res.redirect(url.toString())
148
+
ctx.logger.error({ err }, 'oauth authorize failed')
151
+
err instanceof OAuthResolverError
153
+
: "couldn't initiate login"
155
+
return res.type('html').send(page(login({ error })))
···
handler(async (req: Request, res: Response) => {
164
+
res.setHeader('cache-control', `max-age=${MAX_AGE}, public`)
const service = env.PDS_URL ?? 'https://bsky.social'
const url = await ctx.oauthClient.authorize(service, {
···
handler(async (req: Request, res: Response) => {
192
+
// Never store this route
193
+
res.setHeader('cache-control', 'no-store')
const session = await getIronSession<Session>(req, res, {
password: env.COOKIE_SECRET,
···
handler(async (req: Request, res: Response) => {
220
+
// Prevent caching of this page when the credentials change
221
+
res.setHeader('Vary', 'Cookie')
// If the user is signed in, get an agent which communicates with their server
const agent = await getSessionAgent(req, res, ctx)
···
return res.type('html').send(page(home({ statuses, didHandleMap })))
252
+
// Make sure this page does not get cached in public caches (proxies)
253
+
res.setHeader('cache-control', 'private')
// Fetch additional information about the logged-in user
const profileResponse = await agent.com.atproto.repo
···
// Serve the logged-in view
229
-
res.type('html').send(
276
+
.send(page(home({ statuses, didHandleMap, profile, myStatus })))
···
handler(async (req: Request, res: Response) => {
285
+
// Never store this route
286
+
res.setHeader('cache-control', 'no-store')
// If the user is signed in, get an agent which communicates with their server
const agent = await getSessionAgent(req, res, ctx)
250
-
return res.redirect(`/login`)
253
-
const status = ifString(req.body?.status)
254
-
if (!status || !STATUS_OPTIONS.includes(status)) {
255
-
throw new Error('Invalid status')
294
+
.send('<h1>Error: Session required</h1>')
// Construct & validate their status record
const rkey = TID.nextStr()
$type: 'xyz.statusphere.status',
301
+
status: req.body?.status,
createdAt: new Date().toISOString(),
305
+
// Make sure the record generated from the input is valid
if (!Status.validateRecord(record).success) {
···
.send('<h1>Error: Invalid status</h1>')
273
-
// Write the status record to the user's repository
315
+
// Write the status record to the user's repository
const res = await agent.com.atproto.repo.putRecord({
collection: 'xyz.statusphere.status',
···
354
+
return res.redirect('/')