tangled
alpha
login
or
join now
graham.systems
/
statusphere-react
forked from
samuel.fm/statusphere-react
0
fork
atom
the statusphere demo reworked into a vite/react app in a monorepo
0
fork
atom
overview
issues
pulls
pipelines
Fold src/auth/session into src/routes
Paul Frazee
2 years ago
854f2884
10b67361
+36
-64
2 changed files
expand all
collapse all
unified
split
src
auth
session.ts
routes.ts
-61
src/auth/session.ts
···
1
1
-
import assert from 'node:assert'
2
2
-
import type { IncomingMessage, ServerResponse } from 'node:http'
3
3
-
import { getIronSession } from 'iron-session'
4
4
-
import { env } from '#/lib/env'
5
5
-
import { AppContext } from '#/index'
6
6
-
7
7
-
export type Session = { did: string }
8
8
-
9
9
-
export async function createSession(
10
10
-
req: IncomingMessage,
11
11
-
res: ServerResponse<IncomingMessage>,
12
12
-
did: string
13
13
-
) {
14
14
-
const session = await getSessionRaw(req, res)
15
15
-
assert(!session.did, 'session already exists')
16
16
-
session.did = did
17
17
-
await session.save()
18
18
-
return { did: session.did }
19
19
-
}
20
20
-
21
21
-
export async function destroySession(
22
22
-
req: IncomingMessage,
23
23
-
res: ServerResponse<IncomingMessage>
24
24
-
) {
25
25
-
const session = await getSessionRaw(req, res)
26
26
-
await session.destroy()
27
27
-
return null
28
28
-
}
29
29
-
30
30
-
export async function getSession(
31
31
-
req: IncomingMessage,
32
32
-
res: ServerResponse<IncomingMessage>
33
33
-
) {
34
34
-
const session = await getSessionRaw(req, res)
35
35
-
if (!session.did) return null
36
36
-
return { did: session.did }
37
37
-
}
38
38
-
39
39
-
export async function getSessionAgent(
40
40
-
req: IncomingMessage,
41
41
-
res: ServerResponse<IncomingMessage>,
42
42
-
ctx: AppContext
43
43
-
) {
44
44
-
const session = await getSessionRaw(req, res)
45
45
-
if (!session.did) return null
46
46
-
return await ctx.oauthClient.restore(session.did).catch(async (err) => {
47
47
-
ctx.logger.warn({ err }, 'oauth restore failed')
48
48
-
await destroySession(req, res)
49
49
-
return null
50
50
-
})
51
51
-
}
52
52
-
53
53
-
async function getSessionRaw(
54
54
-
req: IncomingMessage,
55
55
-
res: ServerResponse<IncomingMessage>
56
56
-
) {
57
57
-
return await getIronSession<Session>(req, res, {
58
58
-
cookieName: 'sid',
59
59
-
password: env.COOKIE_SECRET,
60
60
-
})
61
61
-
}
+36
-3
src/routes.ts
···
1
1
+
import assert from 'node:assert'
1
2
import path from 'node:path'
3
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
5
-
import { createSession, destroySession, getSessionAgent } from '#/auth/session'
7
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
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
15
+
type Session = { did: string }
16
16
+
12
17
// Helper function for defining routes
13
18
const handler =
14
19
(fn: express.Handler) =>
···
24
29
}
25
30
}
26
31
32
32
+
// Helper function to get the Atproto Agent for the active session
33
33
+
async function getSessionAgent(
34
34
+
req: IncomingMessage,
35
35
+
res: ServerResponse<IncomingMessage>,
36
36
+
ctx: AppContext
37
37
+
) {
38
38
+
const session = await getIronSession<Session>(req, res, {
39
39
+
cookieName: 'sid',
40
40
+
password: env.COOKIE_SECRET,
41
41
+
})
42
42
+
if (!session.did) return null
43
43
+
return await ctx.oauthClient.restore(session.did).catch(async (err) => {
44
44
+
ctx.logger.warn({ err }, 'oauth restore failed')
45
45
+
await session.destroy()
46
46
+
return null
47
47
+
})
48
48
+
}
49
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
48
-
await createSession(req, res, agent.accountDid)
71
71
+
const session = await getIronSession<Session>(req, res, {
72
72
+
cookieName: 'sid',
73
73
+
password: env.COOKIE_SECRET,
74
74
+
})
75
75
+
assert(!session.did, 'session already exists')
76
76
+
session.did = agent.accountDid
77
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
99
-
await destroySession(req, res)
128
128
+
const session = await getIronSession<Session>(req, res, {
129
129
+
cookieName: 'sid',
130
130
+
password: env.COOKIE_SECRET,
131
131
+
})
132
132
+
await session.destroy()
100
133
return res.redirect('/')
101
134
})
102
135
)