hardening

This commit is contained in:
2026-05-16 10:44:20 +00:00
parent 52e3d680f7
commit cc26ed9b2c
18 changed files with 315 additions and 169 deletions
+36 -26
View File
@@ -2,7 +2,13 @@
import { useRouter } from 'next/navigation'
import { useEffect, useState } from 'react'
import { authFetch, getApiBase, getToken, clearToken } from './lib/auth'
import {
authFetchOrThrow,
ForbiddenError,
getApiBase,
getToken,
UnauthorizedError,
} from './lib/auth'
export default function HomePage() {
const router = useRouter()
@@ -52,13 +58,8 @@ export default function HomePage() {
setRecentError(null)
try {
const baseUrl = getApiBase()
const meResponse = await authFetch(`${baseUrl}/auth/me`)
const meResponse = await authFetchOrThrow(`${baseUrl}/auth/me`)
if (!meResponse.ok) {
if (meResponse.status === 401) {
clearToken()
router.push('/login')
return
}
throw new Error(`Auth failed: ${meResponse.status}`)
}
const me = await meResponse.json()
@@ -66,15 +67,10 @@ export default function HomePage() {
setRole(userRole)
setAuthReady(true)
const take = userRole === 'admin' ? 50 : 6
const response = await authFetch(
const response = await authFetchOrThrow(
`${baseUrl}/requests/recent?take=${take}&days=${recentDays}`
)
if (!response.ok) {
if (response.status === 401) {
clearToken()
router.push('/login')
return
}
throw new Error(`Recent requests failed: ${response.status}`)
}
const data = await response.json()
@@ -99,6 +95,14 @@ export default function HomePage() {
)
}
} catch (error) {
if (error instanceof UnauthorizedError) {
router.push('/login')
return
}
if (error instanceof ForbiddenError) {
router.push('/')
return
}
console.error(error)
setRecentError('Recent requests are not available right now.')
} finally {
@@ -107,7 +111,7 @@ export default function HomePage() {
}
load()
}, [recentDays])
}, [recentDays, router])
useEffect(() => {
if (!authReady) {
@@ -118,18 +122,21 @@ export default function HomePage() {
setServicesError(null)
try {
const baseUrl = getApiBase()
const response = await authFetch(`${baseUrl}/status/services`)
const response = await authFetchOrThrow(`${baseUrl}/status/services`)
if (!response.ok) {
if (response.status === 401) {
clearToken()
router.push('/login')
return
}
throw new Error(`Service status failed: ${response.status}`)
}
const data = await response.json()
setServicesStatus(data)
} catch (error) {
if (error instanceof UnauthorizedError) {
router.push('/login')
return
}
if (error instanceof ForbiddenError) {
router.push('/')
return
}
console.error(error)
setServicesError('Service status is not available right now.')
} finally {
@@ -145,13 +152,8 @@ export default function HomePage() {
const runSearch = async (term: string) => {
try {
const baseUrl = getApiBase()
const response = await authFetch(`${baseUrl}/requests/search?query=${encodeURIComponent(term)}`)
const response = await authFetchOrThrow(`${baseUrl}/requests/search?query=${encodeURIComponent(term)}`)
if (!response.ok) {
if (response.status === 401) {
clearToken()
router.push('/login')
return
}
throw new Error(`Search failed: ${response.status}`)
}
const data = await response.json()
@@ -168,6 +170,14 @@ export default function HomePage() {
setSearchError(null)
}
} catch (error) {
if (error instanceof UnauthorizedError) {
router.push('/login')
return
}
if (error instanceof ForbiddenError) {
router.push('/')
return
}
console.error(error)
setSearchError('Search failed. Try a request ID instead.')
setSearchResults([])