Refactor code structure for improved readability and maintainability

This commit is contained in:
MaddoScientisto 2026-04-12 17:26:17 +02:00
commit c71e4b4cd0
27 changed files with 1738 additions and 324 deletions

View file

@ -9,6 +9,7 @@ export const config = {
frontendUrl: process.env.FACEAI_FRONTEND_URL || 'http://localhost:5173',
publicBaseUrl: process.env.FACEAI_PUBLIC_BASE_URL || 'http://localhost:3001',
legacyReturnUrl: process.env.FACEAI_LEGACY_RETURN_URL || 'http://localhost:3001/dev/legacy/return',
pklRoot: process.env.FACEAI_PKL_ROOT || '/data/pkl',
enableLocalLegacyStatic: process.env.FACEAI_ENABLE_LOCAL_LEGACY_STATIC
? process.env.FACEAI_ENABLE_LOCAL_LEGACY_STATIC === '1'
: process.env.NODE_ENV !== 'production',

View file

@ -0,0 +1,130 @@
import fs from 'node:fs/promises';
import path from 'node:path';
const ITALIAN_MONTH_NAMES = [
'GENNAIO',
'FEBBRAIO',
'MARZO',
'APRILE',
'MAGGIO',
'GIUGNO',
'LUGLIO',
'AGOSTO',
'SETTEMBRE',
'OTTOBRE',
'NOVEMBRE',
'DICEMBRE'
];
function sanitizePathSegment(value) {
const normalized = String(value || '').trim();
if (!normalized) {
return '';
}
if (normalized === '.' || normalized === '..' || normalized.includes('..') || /[\\/]/.test(normalized)) {
throw new Error('Invalid race storage path segment');
}
return normalized;
}
export function normalizeRaceFolderName(value) {
return String(value || '')
.trim()
.replace(/[<>:"/\\|?*]/g, ' ')
.replace(/\s+/g, ' ')
.toUpperCase();
}
export function buildMonthFolder(year, monthIndex) {
const safeYear = sanitizePathSegment(year);
const normalizedMonthIndex = Number(monthIndex);
if (!safeYear || Number.isNaN(normalizedMonthIndex) || normalizedMonthIndex < 1 || normalizedMonthIndex > 12) {
return '';
}
return `${String(normalizedMonthIndex).padStart(2, '0')}.${ITALIAN_MONTH_NAMES[normalizedMonthIndex - 1]}`;
}
export function buildRaceStorage(storageInput = {}) {
const year = sanitizePathSegment(storageInput.year);
const monthFolder = sanitizePathSegment(storageInput.monthFolder);
const raceFolder = sanitizePathSegment(normalizeRaceFolderName(storageInput.raceFolder));
if (!year || !monthFolder || !raceFolder) {
return null;
}
return {
year,
monthFolder,
raceFolder,
relativeDir: path.posix.join(year, monthFolder, raceFolder)
};
}
export async function resolveRacePklAvailability({ pklRoot, race }) {
if (!pklRoot) {
return {
available: false,
reasonCode: 'PKL_ROOT_NOT_CONFIGURED',
message: 'The PKL root is not configured for this FaceAI environment.',
storage: null
};
}
const storage = buildRaceStorage(race?.storage || race);
if (!storage) {
return {
available: false,
reasonCode: 'MISSING_RACE_STORAGE',
message: 'The legacy handoff did not provide the folder metadata required to resolve FaceAI data for this race.',
storage: null
};
}
const raceDir = path.join(pklRoot, storage.year, storage.monthFolder, storage.raceFolder);
let entries;
try {
entries = await fs.readdir(raceDir, { withFileTypes: true });
} catch (error) {
if (error?.code === 'ENOENT') {
return {
available: false,
reasonCode: 'RACE_DIRECTORY_NOT_FOUND',
message: `No FaceAI dataset directory exists for ${storage.relativeDir}.`,
storage,
raceDir
};
}
throw error;
}
const pklEntry = entries
.filter((entry) => entry.isFile() && entry.name.toLowerCase().endsWith('.pkl'))
.sort((left, right) => left.name.localeCompare(right.name, 'en'))[0];
if (!pklEntry) {
return {
available: false,
reasonCode: 'PKL_FILE_NOT_FOUND',
message: `The race directory ${storage.relativeDir} exists, but it does not contain any .pkl file.`,
storage,
raceDir
};
}
return {
available: true,
reasonCode: null,
message: `Using ${storage.relativeDir}/${pklEntry.name}`,
storage,
raceDir,
pklPath: path.join(raceDir, pklEntry.name),
pklFileName: pklEntry.name
};
}

View file

@ -9,6 +9,7 @@ import { fileURLToPath } from 'node:url';
import { config } from './config.js';
import { signPayload, verifySignedPayload } from './auth.js';
import { createSession, getSession, mockCatalog } from './store.js';
import { buildRaceStorage, resolveRacePklAvailability } from './race-storage.js';
import {
acquireActiveSearchLock,
createRedisConnection,
@ -94,8 +95,24 @@ async function enforceSearchRateLimit(req, res, next) {
next();
}
function issueHandoffToken({ raceId, raceSlug, lang, returnUrl }) {
const race = mockCatalog[raceId] || { id: raceId, slug: raceSlug || `race-${raceId}`, name: raceSlug || `Race ${raceId}` };
function normalizeRaceForSession(raceInput) {
return {
...raceInput,
storage: buildRaceStorage(raceInput?.storage || {})
};
}
async function buildRaceAvailability(race) {
return resolveRacePklAvailability({ pklRoot: config.pklRoot, race });
}
function issueHandoffToken({ raceId, raceSlug, raceName, raceStorage, lang, returnUrl }) {
const race = mockCatalog[raceId] || {
id: raceId,
slug: raceSlug || `race-${raceId}`,
name: raceName || raceSlug || `Race ${raceId}`,
storage: buildRaceStorage(raceStorage || {})
};
return signPayload({
type: 'handoff',
@ -108,7 +125,8 @@ function issueHandoffToken({ raceId, raceSlug, lang, returnUrl }) {
race: {
id: race.id,
slug: race.slug,
name: race.name
name: race.name,
storage: buildRaceStorage(raceStorage || race.storage || {})
},
lang: lang || 'it',
returnUrl,
@ -231,9 +249,21 @@ app.get('/dev/legacy/race', (req, res) => {
app.get('/dev/legacy/launch', (req, res) => {
const raceId = String(req.query.raceId || '101');
const raceSlug = String(req.query.raceSlug || mockCatalog[raceId]?.slug || `race-${raceId}`);
const raceName = String(req.query.raceName || mockCatalog[raceId]?.name || raceSlug);
const lang = String(req.query.lang || 'it');
const returnUrl = String(req.query.returnUrl || `${config.publicBaseUrl}/dev/legacy/race?raceId=${encodeURIComponent(raceId)}&lang=${encodeURIComponent(lang)}`);
const token = issueHandoffToken({ raceId, raceSlug, lang, returnUrl });
const token = issueHandoffToken({
raceId,
raceSlug,
raceName,
raceStorage: {
year: String(req.query.raceYear || mockCatalog[raceId]?.storage?.year || ''),
monthFolder: String(req.query.raceMonthFolder || mockCatalog[raceId]?.storage?.monthFolder || ''),
raceFolder: String(req.query.raceFolder || mockCatalog[raceId]?.storage?.raceFolder || '')
},
lang,
returnUrl
});
res.redirect(`${config.frontendUrl}/auth/callback?token=${encodeURIComponent(token)}`);
});
@ -261,7 +291,7 @@ app.get('/dev/legacy/return', async (req, res) => {
}
});
app.post('/api/auth/exchange', (req, res) => {
app.post('/api/auth/exchange', async (req, res) => {
try {
const { token } = req.body;
const payload = verifySignedPayload(token, config.sharedSecret);
@ -269,13 +299,18 @@ app.post('/api/auth/exchange', (req, res) => {
throw new Error('Wrong token type');
}
const race = normalizeRaceForSession(payload.race);
const availability = await buildRaceAvailability(race);
const faceAiAllowed = payload.user.membershipStatus === 'active' && availability.available;
const sessionId = createSession({
user: payload.user,
race: payload.race,
race,
lang: payload.lang,
returnUrl: payload.returnUrl,
availability,
access: {
faceAiAllowed: payload.user.membershipStatus === 'active'
faceAiAllowed
}
});
@ -288,11 +323,12 @@ app.post('/api/auth/exchange', (req, res) => {
res.json({
user: payload.user,
race: payload.race,
race,
lang: payload.lang,
returnUrl: payload.returnUrl,
availability,
access: {
faceAiAllowed: true
faceAiAllowed
}
});
} catch (error) {
@ -308,6 +344,19 @@ app.post('/api/searches', requireSession, enforceSearchRateLimit, upload.single(
try {
const raceId = String(req.body.raceId || req.faceaiSession.race.id);
const userId = String(req.faceaiSession.user.id);
const race = normalizeRaceForSession(raceId === req.faceaiSession.race.id
? req.faceaiSession.race
: (mockCatalog[raceId] || req.faceaiSession.race));
const availability = await buildRaceAvailability(race);
if (!availability.available) {
res.status(409).json({
error: availability.message,
code: availability.reasonCode || 'RACE_PKL_UNAVAILABLE'
});
return;
}
const activeSearchId = await getActiveSearchId(redis, userId);
if (activeSearchId) {
@ -327,10 +376,10 @@ app.post('/api/searches', requireSession, enforceSearchRateLimit, upload.single(
return;
}
const race = mockCatalog[raceId] || req.faceaiSession.race;
const search = await createSearchRecord(redis, {
raceId,
raceName: race?.name || raceId,
raceStorage: race?.storage || availability.storage,
userId,
returnUrl: req.faceaiSession.returnUrl,
lang: req.faceaiSession.lang,
@ -371,6 +420,7 @@ app.post('/api/searches', requireSession, enforceSearchRateLimit, upload.single(
id: updatedSearch.id,
status: updatedSearch.status,
raceId: updatedSearch.raceId,
raceStorage: updatedSearch.raceStorage,
selfieName: updatedSearch.selfieName,
matchCount: updatedSearch.matchCount,
errorCode: updatedSearch.errorCode,

View file

@ -5,6 +5,11 @@ export const mockCatalog = {
id: '101',
slug: 'mezza-di-firenze',
name: 'Mezza di Firenze',
storage: {
year: '2026',
monthFolder: '04.APRILE',
raceFolder: 'PISA'
},
photos: [
{ id: 'f101-001', label: 'Arrivo 001', bib: '245', checkpoint: 'Arrivo', thumb: 'thumb-arrivo-001.jpg' },
{ id: 'f101-002', label: 'Arrivo 002', bib: '245', checkpoint: 'Arrivo', thumb: 'thumb-arrivo-002.jpg' },
@ -22,14 +27,33 @@ export const mockCatalog = {
},
'202': {
id: '202',
slug: 'trail-del-chianti',
name: 'Trail del Chianti',
slug: 'mezza-di-pisa',
name: 'Mezza di Pisa',
storage: {
year: '2026',
monthFolder: '04.APRILE',
raceFolder: 'PISA'
},
photos: [
{ id: 'f202-001', label: 'Bosco 001', bib: '77', checkpoint: 'Bosco', thumb: 'thumb-bosco-001.jpg' },
{ id: 'f202-002', label: 'Salita 002', bib: '77', checkpoint: 'Salita', thumb: 'thumb-salita-002.jpg' },
{ id: 'f202-003', label: 'Arrivo 003', bib: '77', checkpoint: 'Arrivo', thumb: 'thumb-arrivo-003.jpg' },
{ id: 'f202-004', label: 'Bosco 004', bib: '19', checkpoint: 'Bosco', thumb: 'thumb-bosco-004.jpg' }
]
},
'303': {
id: '303',
slug: 'corsa-di-lucca',
name: 'Corsa di Lucca',
storage: {
year: '2026',
monthFolder: '04.APRILE',
raceFolder: 'LUCCA'
},
photos: [
{ id: 'f303-001', label: 'Mura 001', bib: '33', checkpoint: 'Mura', thumb: 'thumb-mura-001.jpg' },
{ id: 'f303-002', label: 'Centro 002', bib: '33', checkpoint: 'Centro', thumb: 'thumb-centro-002.jpg' }
]
}
};