Skip to content

Commit 2acbb44

Browse files
committed
Middleware tweaks; TODOs
1 parent bd72179 commit 2acbb44

File tree

7 files changed

+64
-117
lines changed

7 files changed

+64
-117
lines changed

api/paidAction/territoryDomain.js

Lines changed: 0 additions & 1 deletion
This file was deleted.

api/resolvers/customDomain.js

Lines changed: 0 additions & 43 deletions
This file was deleted.

components/sub-select.js

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ export function useSubs ({ prependSubs = DEFAULT_PREPEND_SUBS, sub, filterSubs =
5252
...appendSubs])
5353
}, [data])
5454

55+
// TODO: can pass custom domain
56+
5557
return subs
5658
}
5759

@@ -79,23 +81,7 @@ export default function SubSelect ({ prependSubs, sub, onChange, size, appendSub
7981
return
8082
}
8183

82-
// Check if we're on a custom domain
83-
84-
// TODO: main domain should be in the env
85-
// If we're on stacker.news and selecting a territory, redirect to territory subdomain
86-
const host = window.location.host
87-
console.log('host', host)
88-
if (host === 'sn.soxa.dev' && sub) {
89-
// Get the base domain (e.g., soxa.dev) from environment or config
90-
const protocol = window.location.protocol
91-
92-
// Create the territory subdomain URL
93-
const territoryUrl = `${protocol}//${sub}.soxa.dev/?source=stackernews`
94-
95-
// Redirect to the territory subdomain
96-
window.location.href = territoryUrl
97-
return
98-
}
84+
// TODO: redirect to the custom domain if it has one
9985

10086
let asPath
10187
// are we currently in a sub (ie not home)

components/territory-form.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export default function TerritoryForm ({ sub }) {
8484
}
8585
}, [sub, billing])
8686

87+
// TODO: Add a custom domain textbox and verification status; validation too
8788
return (
8889
<FeeButtonProvider baseLineItems={lineItems}>
8990
<Form
@@ -274,9 +275,9 @@ export default function TerritoryForm ({ sub }) {
274275
name='nsfw'
275276
groupClassName='ms-1'
276277
/>
277-
<BootstrapForm.Label>personalized domains</BootstrapForm.Label>
278-
<div className='mb-3'>WIP {sub?.customDomain?.domain}</div>
279-
<BootstrapForm.Label>color scheme</BootstrapForm.Label>
278+
<BootstrapForm.Label>personalized domains (TODO textbox/status)</BootstrapForm.Label>
279+
<div className='mb-3'>WIP {sub?.customDomain?.domain || 'not set'}</div>
280+
<BootstrapForm.Label>color scheme (TODO 5 options)</BootstrapForm.Label>
280281
<div className='mb-3'>WIP</div>
281282
</>
282283

docs/user/faq.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,10 @@ The stats for each territory are the following:
267267

268268
You can filter the same stats by different periods in [top territories](/top/territories/day).
269269

270+
### TODO: How can I add a custom domain to a territory?
271+
272+
TODO
273+
270274
---
271275

272276
## Zaps

middleware.js

Lines changed: 49 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,14 @@ const SN_REFERRER_NONCE = 'sn_referrer_nonce'
1111
// key for referred pages
1212
const SN_REFEREE_LANDING = 'sn_referee_landing'
1313

14-
const TERRITORY_PATHS = [
15-
'/',
16-
'/~',
17-
'/recent',
18-
'/random',
19-
'/top',
20-
'/items'
21-
]
14+
const TERRITORY_PATHS = ['/~', '/recent', '/random', '/top', '/post', '/edit']
15+
const NO_REWRITE_PATHS = ['/api', '/_next', '/_error', '/404', '/500', '/offline', '/static', '/items']
2216

2317
function getDomainMapping () {
2418
// placeholder for cachedFetcher
2519
return {
2620
'forum.pizza.com': { subName: 'pizza' }
27-
// placeholder
21+
// placeholder for other domains
2822
}
2923
}
3024

@@ -33,7 +27,9 @@ export function customDomainMiddleware (request, referrerResp) {
3327
const referer = request.headers.get('referer')
3428
const url = request.nextUrl.clone()
3529
const pathname = url.pathname
36-
const mainDomain = process.env.NEXT_PUBLIC_URL
30+
const mainDomain = process.env.NEXT_PUBLIC_URL + '/'
31+
console.log('host', host)
32+
console.log('mainDomain', mainDomain)
3733

3834
console.log('referer', referer)
3935

@@ -43,31 +39,25 @@ export function customDomainMiddleware (request, referrerResp) {
4339
return NextResponse.redirect(new URL(pathname, mainDomain))
4440
}
4541

46-
// For territory paths, handle them directly on the custom domain
47-
if (TERRITORY_PATHS.includes(pathname)) {
48-
// Internally rewrite the request to the territory path without changing the URL
49-
const internalUrl = new URL(url)
42+
if (NO_REWRITE_PATHS.some(p => pathname.startsWith(p)) || pathname.includes('.')) {
43+
return NextResponse.next()
44+
}
5045

51-
// If we're at the root path, internally rewrite to the territory path
52-
if (pathname === '/' || pathname === '/~') {
53-
internalUrl.pathname = `/~${domainInfo.subName}`
54-
console.log('Internal rewrite to:', internalUrl.pathname)
46+
console.log('pathname', pathname)
47+
console.log('query', url.searchParams)
5548

56-
// NextResponse.rewrite() keeps the URL the same for the user
57-
// but internally fetches from the rewritten path
58-
return NextResponse.rewrite(internalUrl)
59-
}
60-
61-
// For other territory paths like /recent, /top, etc.
62-
// We need to rewrite them to the territory-specific versions
63-
if (pathname === '/recent' || pathname === '/top' || pathname === '/random' || pathname === '/items') {
64-
internalUrl.pathname = `/~${domainInfo.subName}${pathname}`
65-
console.log('Internal rewrite to:', internalUrl.pathname)
66-
return NextResponse.rewrite(internalUrl)
67-
}
49+
// if the url contains the territory path, remove it
50+
if (pathname.startsWith(`/~${domainInfo.subName}`)) {
51+
// remove the territory prefix from the path
52+
const cleanPath = pathname.replace(`/~${domainInfo.subName}`, '') || '/'
53+
console.log('Redirecting to clean path:', cleanPath)
54+
return NextResponse.redirect(new URL(cleanPath + url.search, url.origin))
55+
}
6856

69-
// Handle auth if needed
70-
if (!referer || referer !== mainDomain) {
57+
// if territory path, retain custom domain
58+
if (pathname === '/' || TERRITORY_PATHS.some(p => pathname.startsWith(p))) {
59+
// if coming from main domain, handle auth automatically
60+
if (referer && referer === mainDomain) {
7161
const authResp = customDomainAuthMiddleware(request, url)
7262
if (authResp && authResp.status !== 200) {
7363
// copy referrer cookies to auth redirect
@@ -77,7 +67,15 @@ export function customDomainMiddleware (request, referrerResp) {
7767
return authResp
7868
}
7969
}
80-
return referrerResp
70+
71+
const internalUrl = new URL(url)
72+
73+
// rewrite to the territory path if we're at the root
74+
internalUrl.pathname = `/~${domainInfo.subName}${pathname === '/' ? '' : pathname}`
75+
console.log('Rewrite to:', internalUrl.pathname)
76+
77+
// rewrite to the territory path
78+
return NextResponse.rewrite(internalUrl)
8179
}
8280

8381
// redirect to main domain for non-territory paths
@@ -93,7 +91,7 @@ export function customDomainMiddleware (request, referrerResp) {
9391
}
9492

9593
// TODO: dirty of previous iterations, refactor
96-
// Not safe, tokens are visible in the URL
94+
// UNSAFE UNSAFE UNSAFE tokens are visible in the URL
9795
export function customDomainAuthMiddleware (request, url) {
9896
const pathname = url.pathname
9997
const host = request.headers.get('host')
@@ -114,7 +112,6 @@ export function customDomainAuthMiddleware (request, url) {
114112
const response = NextResponse.next()
115113

116114
if (!hasSession && isCustomDomain) {
117-
// Use the original request's host and protocol for the redirect URL
118115
// TODO: original request url points to localhost, this is a workaround atm
119116
const protocol = secure ? 'https' : 'http'
120117
const originalDomain = `${protocol}://${host}`
@@ -206,22 +203,7 @@ function referrerMiddleware (request) {
206203
return response
207204
}
208205

209-
export function middleware (request) {
210-
const host = request.headers.get('host')
211-
const isCustomDomain = host !== process.env.NEXT_PUBLIC_URL.replace(/^https?:\/\//, '')
212-
213-
// First run referrer middleware to capture referrer data
214-
const referrerResp = referrerMiddleware(request)
215-
216-
// If we're on a custom domain, handle that next
217-
if (isCustomDomain) {
218-
return customDomainMiddleware(request, referrerResp)
219-
}
220-
221-
const resp = referrerResp
222-
223-
// TODO: This doesn't run for custom domains, need to support it
224-
206+
export function applySecurityHeaders (resp) {
225207
const isDev = process.env.NODE_ENV === 'development'
226208

227209
const nonce = Buffer.from(crypto.randomUUID()).toString('base64')
@@ -268,6 +250,22 @@ export function middleware (request) {
268250
return resp
269251
}
270252

253+
export function middleware (request) {
254+
const host = request.headers.get('host')
255+
const isCustomDomain = host !== process.env.NEXT_PUBLIC_URL.replace(/^https?:\/\//, '')
256+
257+
// First run referrer middleware to capture referrer data
258+
const referrerResp = referrerMiddleware(request)
259+
260+
// If we're on a custom domain, handle that next
261+
if (isCustomDomain) {
262+
const customDomainResp = customDomainMiddleware(request, referrerResp)
263+
return applySecurityHeaders(customDomainResp)
264+
}
265+
266+
return applySecurityHeaders(referrerResp)
267+
}
268+
271269
export const config = {
272270
matcher: [
273271
// NextJS recommends to not add the CSP header to prefetches and static assets

pages/api/auth/sync.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { getAuthOptions } from './[...nextauth]'
33
import { serialize } from 'cookie'
44
import { datePivot } from '@/lib/time'
55

6-
// TODO: not safe, tokens are visible in the URL
6+
// TODO: dirty of previous iterations, refactor
7+
// UNSAFE UNSAFE UNSAFE tokens are visible in the URL
78
export default async function handler (req, res) {
89
console.log(req.query)
910
if (req.query.token) {
@@ -12,6 +13,7 @@ export default async function handler (req, res) {
1213
} else {
1314
const { redirectUrl } = req.query
1415
const session = await getServerSession(req, res, getAuthOptions(req))
16+
// TODO: use session to create a verification token
1517
if (session) {
1618
console.log('session', session)
1719
console.log('req.cookies', req.cookies)
@@ -43,12 +45,12 @@ export default async function handler (req, res) {
4345
}
4446

4547
export async function saveCookie (req, res, tokenData) {
46-
const secure = process.env.NODE_ENV === 'development'
4748
if (!tokenData) {
4849
return res.status(400).json({ error: 'Missing token' })
4950
}
5051

5152
try {
53+
const secure = process.env.NODE_ENV === 'development'
5254
const expiresAt = datePivot(new Date(), { months: 1 })
5355
const cookieOptions = {
5456
path: '/',

0 commit comments

Comments
 (0)