Preserve monthly recap destinations through sign-in
This commit is contained in:
@@ -71,7 +71,10 @@ export default function LoginPage() {
|
|||||||
if (!data?.authenticated) { setError('Could not sign in. Please try again.'); return }
|
if (!data?.authenticated) { setError('Could not sign in. Please try again.'); return }
|
||||||
setToken('cookie')
|
setToken('cookie')
|
||||||
const next = new URLSearchParams(window.location.search).get('next') || ''
|
const next = new URLSearchParams(window.location.search).get('next') || ''
|
||||||
window.location.assign(next === '/insights' || /^\/issues\/confirm\/\d+$/.test(next) ? next : '/welcome')
|
const allowedNext = ['/insights', '/insights/reports', '/profile', '/profile#monthly-recaps', '/admin/recaps'].includes(next)
|
||||||
|
|| /^\/insights\/reports\?month=[0-9]{4}-(?:0[1-9]|1[0-2])$/.test(next)
|
||||||
|
|| /^\/issues\/confirm\/\d+$/.test(next)
|
||||||
|
window.location.assign(allowedNext ? next : '/welcome')
|
||||||
} catch {
|
} catch {
|
||||||
setError('Could not reach Magent. Check your connection and try again.')
|
setError('Could not reach Magent. Check your connection and try again.')
|
||||||
} finally { setLoading(false) }
|
} finally { setLoading(false) }
|
||||||
|
|||||||
@@ -69,12 +69,12 @@ export default function ProfilePage() {
|
|||||||
const [showAllActivity, setShowAllActivity] = useState(false)
|
const [showAllActivity, setShowAllActivity] = useState(false)
|
||||||
|
|
||||||
const loadProfile = useCallback(async () => {
|
const loadProfile = useCallback(async () => {
|
||||||
if (!getToken()) { router.replace('/login'); return }
|
if (!getToken()) { router.replace('/login?next=%2Fprofile'); return }
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
setLoadError('')
|
setLoadError('')
|
||||||
try {
|
try {
|
||||||
const response = await authFetch(`${getApiBase()}/auth/profile`)
|
const response = await authFetch(`${getApiBase()}/auth/profile`)
|
||||||
if (response.status === 401) { clearToken(); router.replace('/login'); return }
|
if (response.status === 401) { clearToken(); router.replace('/login?next=%2Fprofile'); return }
|
||||||
if (!response.ok) throw new Error('Could not load your profile. Please try again.')
|
if (!response.ok) throw new Error('Could not load your profile. Please try again.')
|
||||||
const profile = await response.json() as ProfileResponse
|
const profile = await response.json() as ProfileResponse
|
||||||
setData(profile)
|
setData(profile)
|
||||||
@@ -120,7 +120,7 @@ export default function ProfilePage() {
|
|||||||
method: 'PUT', headers: { 'Content-Type': 'application/json' },
|
method: 'PUT', headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ email: email.trim() || null }),
|
body: JSON.stringify({ email: email.trim() || null }),
|
||||||
})
|
})
|
||||||
if (response.status === 401) { clearToken(); router.replace('/login'); return }
|
if (response.status === 401) { clearToken(); router.replace('/login?next=%2Fprofile'); return }
|
||||||
if (!response.ok) throw new Error(await responseMessage(response, 'Could not save your email. Please try again.'))
|
if (!response.ok) throw new Error(await responseMessage(response, 'Could not save your email. Please try again.'))
|
||||||
const result = await response.json()
|
const result = await response.json()
|
||||||
const saved = typeof result.email === 'string' ? result.email : ''
|
const saved = typeof result.email === 'string' ? result.email : ''
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ const output = process.env.REVIEW_DIR
|
|||||||
const url = new URL(request.url())
|
const url = new URL(request.url())
|
||||||
calls.push({ method: request.method(), path: url.pathname, month: url.searchParams.get('month') })
|
calls.push({ method: request.method(), path: url.pathname, month: url.searchParams.get('month') })
|
||||||
if (url.pathname === '/api/auth/me') return route.fulfill({ json: { username: 'Fixture viewer', role } })
|
if (url.pathname === '/api/auth/me') return route.fulfill({ json: { username: 'Fixture viewer', role } })
|
||||||
|
if (url.pathname === '/api/auth/jellyfin/login' || url.pathname === '/api/auth/login') return route.fulfill({ json: { authenticated: true } })
|
||||||
if (url.pathname.startsWith('/api/insights/artwork/')) return route.fulfill({ contentType: 'image/svg+xml', body: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 180"><rect width="120" height="180" fill="#243946"/><path d="M0 150L65 35L120 150" fill="#c8bdaa"/></svg>' })
|
if (url.pathname.startsWith('/api/insights/artwork/')) return route.fulfill({ contentType: 'image/svg+xml', body: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 180"><rect width="120" height="180" fill="#243946"/><path d="M0 150L65 35L120 150" fill="#c8bdaa"/></svg>' })
|
||||||
if (url.pathname === '/api/insights/reports/monthly.csv') {
|
if (url.pathname === '/api/insights/reports/monthly.csv') {
|
||||||
if (failDownload) return route.fulfill({ status: 502, json: { detail: 'Unavailable' } })
|
if (failDownload) return route.fulfill({ status: 502, json: { detail: 'Unavailable' } })
|
||||||
@@ -138,6 +139,19 @@ const output = process.env.REVIEW_DIR
|
|||||||
await page.waitForURL(/\/login\?next=/)
|
await page.waitForURL(/\/login\?next=/)
|
||||||
assert.equal(new URL(page.url()).searchParams.get('next'), `/insights/reports?month=${months.at(-1)}`)
|
assert.equal(new URL(page.url()).searchParams.get('next'), `/insights/reports?month=${months.at(-1)}`)
|
||||||
mode = 'ready'
|
mode = 'ready'
|
||||||
|
await page.getByLabel('Username', { exact: true }).fill('fixture-viewer')
|
||||||
|
await page.getByLabel('Password', { exact: true }).fill('Fixture-only-password')
|
||||||
|
await page.getByRole('button', { name: 'Sign in', exact: true }).click()
|
||||||
|
await page.getByRole('heading', { name: 'October 2024', exact: true }).waitFor()
|
||||||
|
assert.equal(new URL(page.url()).searchParams.get('month'), months.at(-1))
|
||||||
|
// An external or unrecognized destination must still use the safe welcome fallback.
|
||||||
|
for (const next of ['https://outside.example.test', '//outside.example.test', '/insights/reports?month=2026-07&redirect=https://outside.example.test']) {
|
||||||
|
await page.goto(`${base}/login?next=${encodeURIComponent(next)}`)
|
||||||
|
await page.getByLabel('Username', { exact: true }).fill('fixture-viewer')
|
||||||
|
await page.getByLabel('Password', { exact: true }).fill('Fixture-only-password')
|
||||||
|
await page.getByRole('button', { name: 'Sign in', exact: true }).click()
|
||||||
|
await page.waitForURL(`${base}/welcome`)
|
||||||
|
}
|
||||||
await page.goto(base + '/insights/reports')
|
await page.goto(base + '/insights/reports')
|
||||||
await page.getByRole('heading', { name: 'August 2026', exact: true }).waitFor()
|
await page.getByRole('heading', { name: 'August 2026', exact: true }).waitFor()
|
||||||
await page.getByRole('navigation', { name: 'My Stats views' }).getByRole('link', { name: 'Overview' }).click()
|
await page.getByRole('navigation', { name: 'My Stats views' }).getByRole('link', { name: 'Overview' }).click()
|
||||||
|
|||||||
Reference in New Issue
Block a user