Public Access
feat(auth): tell the user when the session expired
Every 401 from Auth or Core now goes through useSessionExpired: the login page says the session expired and returns to the last page after login. App no longer removes a token that only the browser clock calls expired, so a backend 401 is the one signal. A 403 on the profile now shows an error instead.
This commit is contained in:
1 parent
03259d0515
commit
d4c0f8d8f3
19 files changed
+351
-35
No files matched your search
+26
-8
@@ -16,6 +16,7 @@ import SyncStatusBadge from '../components/SyncStatusBadge.jsx';
|
||||
import useLibrarySync from '../hooks/useLibrarySync.js';
|
||||
import useForceSync from '../hooks/useForceSync.js';
|
||||
import {formatPlaytime} from '../utils/games.js';
|
||||
import useSessionExpired from '../hooks/useSessionExpired.js';
|
||||
|
||||
const TOP_GAMES = 5;
|
||||
// The games endpoint accepts only the page sizes 20, 40 and 80.
|
||||
@@ -31,6 +32,7 @@ const authHeaders = () => ({
|
||||
const Dashboard = () => {
|
||||
const {t} = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const expireSession = useSessionExpired();
|
||||
const [userData, setUserData] = useState(null);
|
||||
const [steamData, setSteamData] = useState({count: 0, hasSteamId: false});
|
||||
const [topGames, setTopGames] = useState([]);
|
||||
@@ -44,17 +46,25 @@ const Dashboard = () => {
|
||||
const fetchSteamCount = useCallback(async () => {
|
||||
try {
|
||||
const r = await fetch(`${import.meta.env.VITE_CORE_API_URL}/api/library/games-count`, {headers: authHeaders()});
|
||||
if (r.status === 401) {
|
||||
expireSession();
|
||||
return;
|
||||
}
|
||||
if (r.ok) {
|
||||
setSteamData(await r.json());
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error fetching steam data:', err);
|
||||
}
|
||||
}, []);
|
||||
}, [expireSession]);
|
||||
|
||||
const fetchTopGames = useCallback(async () => {
|
||||
try {
|
||||
const r = await fetch(`${import.meta.env.VITE_CORE_API_URL}${TOP_GAMES_URL}`, {headers: authHeaders()});
|
||||
if (r.status === 401) {
|
||||
expireSession();
|
||||
return;
|
||||
}
|
||||
if (r.ok) {
|
||||
const page = await r.json();
|
||||
setTopGames((page.content ?? []).slice(0, TOP_GAMES));
|
||||
@@ -62,11 +72,15 @@ const Dashboard = () => {
|
||||
} catch (err) {
|
||||
console.error('Error fetching top games:', err);
|
||||
}
|
||||
}, []);
|
||||
}, [expireSession]);
|
||||
|
||||
const fetchPlaying = useCallback(async () => {
|
||||
try {
|
||||
const r = await fetch(`${import.meta.env.VITE_CORE_API_URL}${PLAYING_URL}`, {headers: authHeaders()});
|
||||
if (r.status === 401) {
|
||||
expireSession();
|
||||
return;
|
||||
}
|
||||
if (r.ok) {
|
||||
const page = await r.json();
|
||||
setPlaying((page.content ?? []).slice(0, PLAYING_GAMES));
|
||||
@@ -74,7 +88,7 @@ const Dashboard = () => {
|
||||
} catch (err) {
|
||||
console.error('Error fetching playing games:', err);
|
||||
}
|
||||
}, []);
|
||||
}, [expireSession]);
|
||||
|
||||
/**
|
||||
* @param excludeAppid the current suggestion, so the new pick differs from it
|
||||
@@ -84,6 +98,10 @@ const Dashboard = () => {
|
||||
const query = excludeAppid ? `?exclude=${excludeAppid}` : '';
|
||||
try {
|
||||
const r = await fetch(`${import.meta.env.VITE_CORE_API_URL}/api/library/summary${query}`, {headers: authHeaders()});
|
||||
if (r.status === 401) {
|
||||
expireSession();
|
||||
return true;
|
||||
}
|
||||
if (r.ok) {
|
||||
setSummary(await r.json());
|
||||
setSummaryFailed(false);
|
||||
@@ -94,7 +112,7 @@ const Dashboard = () => {
|
||||
}
|
||||
setSummaryFailed(true);
|
||||
return false;
|
||||
}, []);
|
||||
}, [expireSession]);
|
||||
|
||||
const shuffleSuggestion = async () => {
|
||||
setShuffling(true);
|
||||
@@ -131,9 +149,8 @@ const Dashboard = () => {
|
||||
if (data.steamId) {
|
||||
await Promise.all([fetchSteamCount(), fetchTopGames(), fetchPlaying(), fetchSummary()]);
|
||||
}
|
||||
} else if (profileResponse.status === 401 || profileResponse.status === 403) {
|
||||
localStorage.removeItem('tbp_jwt');
|
||||
navigate('/login');
|
||||
} else if (profileResponse.status === 401) {
|
||||
expireSession();
|
||||
} else {
|
||||
setError(t('INFO.ERROR.LOAD_PROFILE'));
|
||||
}
|
||||
@@ -146,13 +163,14 @@ const Dashboard = () => {
|
||||
};
|
||||
|
||||
fetchUserData();
|
||||
}, [navigate, t, fetchSteamCount, fetchTopGames, fetchPlaying, fetchSummary]);
|
||||
}, [navigate, expireSession, t, fetchSteamCount, fetchTopGames, fetchPlaying, fetchSummary]);
|
||||
|
||||
const hasSteamId = !!userData?.steamId;
|
||||
const sync = useLibrarySync({
|
||||
enabled: hasSteamId,
|
||||
expectInitialSync: hasSteamId && steamData.count === 0,
|
||||
onComplete: reloadLibrary,
|
||||
onUnauthorized: expireSession,
|
||||
});
|
||||
const forceSync = useForceSync(reloadLibrary);
|
||||
|
||||
|
||||
Reference in new issue
Block a user