Enhance session management and player data handling

- Updated `requireSession.js` to ensure `req.body` and `req.query` are always objects before access, improving robustness against malformed requests.
- Changed API endpoint for login from `/api/sessions/login` to `/api/players/login` in `App.js`, updating related logging and state management to reflect the new structure.
- Enhanced player fetching logic in `PlayerTab.jsx` to handle cases where GM is logged in, ensuring all players are fetched from the API. Added debug logging for better traceability.
- Implemented fallback to stored player data if API fetch fails, ensuring a smoother user experience for regular players.
- Updated local storage handling to accommodate changes in player data structure.
This commit is contained in:
2025-08-16 00:06:50 +02:00
parent 73e44ffcdb
commit ec487b0614
7 changed files with 787 additions and 15 deletions
+10 -9
View File
@@ -76,19 +76,20 @@ function App() {
const handleLogin = async () => {
try {
logUserAction('user', 'Login attempt', { username: loginName });
const response = await axios.post('/api/sessions/login', {
username: loginName,
const response = await axios.post('/api/players/login', {
name: loginName,
password: loginPw
});
logApiCall('POST', '/api/sessions/login', { username: loginName }, response.status);
logApiCall('POST', '/api/players/login', { name: loginName }, response.status);
if (response.data.success) {
// Update global state with session info
setAuthedPlayer(response.data.playerName);
if (response.data.sessionId && response.data.player) {
// Update global state with session info and player data
setAuthedPlayer(response.data.player.name);
setSessionId(response.data.sessionId);
localStorage.setItem('dw:shop:authedPlayer', JSON.stringify(response.data.playerName));
localStorage.setItem('dw:shop:authedPlayer', JSON.stringify(response.data.player.name));
localStorage.setItem('dw:shop:sessionId', JSON.stringify(response.data.sessionId));
localStorage.setItem('dw:shop:playerData', JSON.stringify(response.data.player));
info(`Login successful for user: ${loginName}`, 'auth');
logUserAction('user', 'Login successful', { username: loginName });
@@ -99,14 +100,14 @@ function App() {
// Clear success message after 3 seconds
setTimeout(() => setLoginMsg(''), 3000);
} else {
warn(`Login failed for user: ${loginName} - ${response.data.message}`, 'auth');
warn(`Login failed for user: ${loginName} - ${response.data.message || 'Unknown error'}`, 'auth');
setLoginMsg(response.data.message || 'Login failed');
// Clear error message after 5 seconds
setTimeout(() => setLoginMsg(''), 5000);
}
} catch (err) {
logApiError('POST', '/api/sessions/login', err);
logApiError('POST', '/api/players/login', err);
error(`Login error for user: ${loginName} - ${err.message}`, 'auth');
setLoginMsg('Login failed. Please check your credentials and try again.');
+40 -2
View File
@@ -233,6 +233,37 @@ function PlayerTab({
useEffect(() => {
async function fetchPlayers() {
try {
console.log('DEBUG: fetchPlayers called, isGMLoggedIn():', isGMLoggedIn(), 'authedPlayer:', authedPlayer);
// If GM is logged in, always fetch all players from API
if (isGMLoggedIn()) {
console.log('DEBUG: GM is logged in, fetching all players from API');
logApiCall('PlayerTab', 'GET', '/api/players');
const response = await axios.get('/api/players', { headers: buildHeaders() });
const data = response.data;
console.log('DEBUG: GM API response:', data.length, 'players');
if (!Array.isArray(data)) {
warn('PlayerTab', '/api/players did not return an array', data);
setPlayers([]);
} else {
info('PlayerTab', `Fetched ${data.length} players`);
setPlayers(data);
safeSet(STORAGE_SHOP_PLAYERS, data);
}
return;
}
console.log('DEBUG: Not GM, checking stored data');
// For regular players, try to get stored player data from login first
const storedPlayerData = safeGet('dw:shop:playerData');
if (storedPlayerData && authedPlayer) {
console.log('DEBUG: Using stored player data for regular user');
// If we have stored player data and user is logged in, use it
setPlayers([storedPlayerData]);
return;
}
console.log('DEBUG: Fetching from API for regular user');
logApiCall('PlayerTab', 'GET', '/api/players');
const response = await axios.get('/api/players', { headers: buildHeaders() });
const data = response.data;
@@ -245,14 +276,21 @@ function PlayerTab({
safeSet(STORAGE_SHOP_PLAYERS, data);
}
} catch (apiError) {
console.log('DEBUG: API error:', apiError);
logApiError('PlayerTab', 'GET', '/api/players', apiError);
setPlayers([]);
// If API fails but we have stored player data, use that
const storedPlayerData = safeGet('dw:shop:playerData');
if (storedPlayerData && authedPlayer) {
setPlayers([storedPlayerData]);
} else {
setPlayers([]);
}
}
}
fetchPlayers();
// Add buildHeaders to dependencies since it's used in fetchPlayers
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [sessionId, gmOpen]);
}, [sessionId, gmOpen, authedPlayer]);
// Update player data in the database
async function updatePlayerData(updatedPlayer) {