Files
memory-infrastructure-palace/code/websites/pokedex.online/server/routes/session.js
FragginWagon 8775f8b1fe Refactor code for improved readability and consistency
- Updated CSRF middleware to enhance cookie value decoding.
- Reformatted OAuth proxy token store initialization for better clarity.
- Adjusted Challonge proxy router for consistent line breaks and readability.
- Enhanced OAuth router error handling and response formatting.
- Improved session router for better readability and consistency in fetching provider records.
- Refactored OAuth token store to improve key derivation logging.
- Cleaned up cookie options utility for better readability.
- Enhanced Challonge client credentials composable for consistent API calls.
- Streamlined OAuth composable for improved logging.
- Refactored main.js for better readability in session initialization.
- Improved Challonge v2.1 service error handling for better clarity.
- Cleaned up API client utility for improved readability.
- Enhanced ApiKeyManager.vue for better text formatting.
- Refactored ChallongeTest.vue for improved readability in composable usage.
2026-02-03 12:50:25 -05:00

168 lines
4.9 KiB
JavaScript

import express from 'express';
import fetch from 'node-fetch';
import {
COOKIE_NAMES,
getCsrfCookieOptions,
generateToken
} from '../utils/cookie-options.js';
export function createSessionRouter({ config, tokenStore }) {
const router = express.Router();
async function probeChallonge(url, headers) {
try {
const resp = await fetch(url, { method: 'GET', headers });
const contentType = resp.headers.get('content-type') || '';
let bodyText = '';
try {
bodyText = await resp.text();
} catch {
bodyText = '';
}
// Keep response small & safe
const snippet = (bodyText || '').slice(0, 500);
let json = null;
if (contentType.includes('application/json')) {
try {
json = bodyText ? JSON.parse(bodyText) : null;
} catch {
json = null;
}
}
return {
ok: resp.ok,
status: resp.status,
contentType,
snippet,
json
};
} catch (err) {
return {
ok: false,
status: null,
contentType: null,
snippet: err?.message || 'probe failed',
json: null
};
}
}
// Ensure SID exists (sid middleware should run before this)
router.get('/init', async (req, res) => {
try {
if (!req.sid) {
return res.status(500).json({ error: 'SID middleware not configured' });
}
await tokenStore.touchSession(req.sid);
return res.json({ ok: true });
} catch (err) {
return res.status(500).json({
error: err.message || 'Failed to init session',
code: 'SESSION_INIT_FAILED'
});
}
});
// Issue/refresh CSRF token cookie
router.get('/csrf', (req, res) => {
const token = generateToken(24);
res.cookie(COOKIE_NAMES.csrf, token, getCsrfCookieOptions(config));
res.json({ csrfToken: token });
});
// Dev helper: confirm which SID the browser is using and whether provider
// credentials are present for that SID. Does not return secrets.
router.get('/whoami', async (req, res) => {
if (!req.sid) {
return res.status(500).json({ error: 'SID middleware not configured' });
}
const challonge =
(await tokenStore.getProviderRecord(req.sid, 'challonge')) || {};
return res.json({
sid: req.sid,
challonge: {
hasApiKey: !!challonge.api_key?.token,
hasUserOAuth: !!challonge.user_oauth?.access_token,
userOAuthExpiresAt: challonge.user_oauth?.expires_at || null,
hasClientCredentials: !!(
challonge.client_credentials?.client_id &&
challonge.client_credentials?.client_secret
),
hasClientCredentialsToken: !!challonge.client_credentials?.access_token,
clientCredentialsExpiresAt:
challonge.client_credentials?.expires_at || null
}
});
});
// Dev-only: verify challonge upstream auth for this SID (no secrets returned)
router.get('/challonge/verify', async (req, res) => {
if (!req.sid) {
return res.status(500).json({ error: 'SID middleware not configured' });
}
const challonge =
(await tokenStore.getProviderRecord(req.sid, 'challonge')) || {};
const base =
'https://api.challonge.com/v2.1/tournaments.json?page=1&per_page=1&state=pending';
const results = {
sid: req.sid,
endpoints: {
userTournamentsSample: base,
appTournamentsSample:
'https://api.challonge.com/v2.1/application/tournaments.json?page=1&per_page=1&state=pending'
},
methods: {
user_oauth: {
present: !!challonge.user_oauth?.access_token,
probe: null
},
api_key: { present: !!challonge.api_key?.token, probe: null },
client_credentials: {
present: !!challonge.client_credentials?.access_token,
probe: null
}
}
};
if (challonge.user_oauth?.access_token) {
results.methods.user_oauth.probe = await probeChallonge(base, {
Accept: 'application/json',
'Content-Type': 'application/vnd.api+json',
authorization: `Bearer ${challonge.user_oauth.access_token}`,
'authorization-type': 'v2'
});
}
if (challonge.api_key?.token) {
results.methods.api_key.probe = await probeChallonge(base, {
Accept: 'application/json',
'Content-Type': 'application/vnd.api+json',
authorization: challonge.api_key.token,
'authorization-type': 'v1'
});
}
if (challonge.client_credentials?.access_token) {
results.methods.client_credentials.probe = await probeChallonge(
results.endpoints.appTournamentsSample,
{
Accept: 'application/json',
'Content-Type': 'application/vnd.api+json',
authorization: `Bearer ${challonge.client_credentials.access_token}`,
'authorization-type': 'v2'
}
);
}
return res.json(results);
});
return router;
}