Finish server restructuring

This commit is contained in:
pedrocx486 2025-01-31 18:23:40 -03:00
parent f4258fb35f
commit 136c51ba46
3 changed files with 91 additions and 83 deletions

View file

@ -50,66 +50,66 @@ router.post('/createPartyLine', [
// Route to delete a party line
router.delete('/deletePartyLine', [
body('partyLine').isString().trim().escape().notEmpty().withMessage('Invalid party line name')
], (req: any, res: any) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
body('partyLine').isString().trim().escape().notEmpty().withMessage('Invalid party line name')
], (req: any, res: any) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
try {
const { partyLine: currentPartyLine } = req.body;
const partyLine = partyLines[currentPartyLine];
if (!partyLine) {
return res.status(404).send({ status: 'Party line not found' });
}
try {
const { partyLine: currentPartyLine } = req.body;
const partyLine = partyLines[currentPartyLine];
if (!partyLine) {
return res.status(404).send({ status: 'Party line not found' });
}
// Broadcast deletion message to all clients
broadcast(currentPartyLine, 'PARTY_LINE_DELETED');
// Disconnect all clients
partyLine.clients.forEach((client: any) => {
console.log(`DISCONNECTING: { partyLine: ${currentPartyLine}, clientId: ${client.clientId} }`);
client.response.end();
});
// Delete the party line
delete partyLines[currentPartyLine];
console.log(`DELETE: { partyLine: ${currentPartyLine} }`);
res.status(200).send({ status: 'Party line deleted', currentPartyLine });
} catch (error) {
console.error('ERROR: Failed to delete party line', error);
res.status(500).send({ status: 'Internal server error' });
}
});
// Route to send an event to a party line
// Broadcast deletion message to all clients
broadcast(currentPartyLine, 'PARTY_LINE_DELETED');
// Disconnect all clients
partyLine.clients.forEach((client: any) => {
console.log(`DISCONNECTING: { partyLine: ${currentPartyLine}, clientId: ${client.clientId} }`);
client.response.end();
});
// Delete the party line
delete partyLines[currentPartyLine];
console.log(`DELETE: { partyLine: ${currentPartyLine} }`);
res.status(200).send({ status: 'Party line deleted', currentPartyLine });
} catch (error) {
console.error('ERROR: Failed to delete party line', error);
res.status(500).send({ status: 'Internal server error' });
}
});
// Route to send an event to a party line
router.post('/rumor', [
body('partyLine').isString().trim().escape().notEmpty().withMessage('Invalid party line name'),
body('rumor').isString().trim().escape().notEmpty().withMessage('Invalid rumor')
], (req: any, res: any) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
body('partyLine').isString().trim().escape().notEmpty().withMessage('Invalid party line name'),
body('rumor').isString().trim().escape().notEmpty().withMessage('Invalid rumor')
], (req: any, res: any) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
try {
const { partyLine: connectedPartyLine, rumor } = req.body;
const partyLine = partyLines[connectedPartyLine];
if (!partyLine) {
return res.status(404).send({ status: 'Party line not found' });
}
try {
const { partyLine: connectedPartyLine, rumor } = req.body;
const partyLine = partyLines[connectedPartyLine];
if (!partyLine) {
return res.status(404).send({ status: 'Party line not found' });
}
console.log(`RECEIVE: { partyLine: ${connectedPartyLine}, rumor: ${rumor} }`);
// Update the last event and broadcast it to all clients
partyLine.lastEvent = rumor;
partyLine.clients.forEach((client: any) => {
client.response.write(`data: ${rumor}\n\n`);
});
res.status(200).send({ status: 'Rumor broadcast' });
} catch (error) {
console.error('ERROR: Failed to send event', error);
res.status(500).send({ status: 'Internal server error' });
}
});
export default router;
console.log(`RECEIVE: { partyLine: ${connectedPartyLine}, rumor: ${rumor} }`);
// Update the last event and broadcast it to all clients
partyLine.lastEvent = rumor;
partyLine.clients.forEach((client: any) => {
client.response.write(`data: ${rumor}\n\n`);
});
res.status(200).send({ status: 'Rumor broadcast' });
} catch (error) {
console.error('ERROR: Failed to send event', error);
res.status(500).send({ status: 'Internal server error' });
}
});
export default router;

View file

@ -4,12 +4,11 @@ import cors from 'cors';
import bodyParser from 'body-parser';
import helmet from 'helmet';
import path from 'path';
import { partyLines } from './stores/dataStore';
import { ENVIRONMENT, PORT, CLIENT_URL, DOCKER } from './stores/configStore';
import { broadcast } from './services/broadcastService';
import connectionRoutes from './routes/connectionRoutes';
import managementRoutes from './routes/managementRoutes';
import navigationRoutes from './routes/navigationRoutes';
import { maintenanceService } from "./services/maintenanceService";
const app = express();
@ -35,6 +34,8 @@ app.use(cors(corsOptions));
app.use(bodyParser.json());
app.use(helmet());
app.use(limiter);
// Serve the client's static files
app.use('/', express.static(path.join(__dirname, '../static')));
// Force HTTPS redirection and CSP in production
@ -47,21 +48,21 @@ if (ENVIRONMENT === 'production') {
});
app.use(
helmet.contentSecurityPolicy({
useDefaults: true,
directives: {
'script-src': ['\'self\''],
'img-src': ['\'self\'', 'data:'],
'connect-src': ['\'self\'']
}
})
helmet.contentSecurityPolicy({
useDefaults: true,
directives: {
'script-src': ['\'self\''],
'img-src': ['\'self\'', 'data:'],
'connect-src': ['\'self\'']
}
})
);
} else {
// Disable CSP for non-prod
app.use(
helmet({
contentSecurityPolicy: false,
}),
helmet({
contentSecurityPolicy: false,
}),
);
}
@ -70,19 +71,10 @@ app.use(navigationRoutes);
app.use(managementRoutes);
app.use(connectionRoutes);
// Periodically resend the last rumor and clean up inactive party lines
// Periodically run the maintenance service
// Which is: Resend the last rumor and clean up inactive party lines
setInterval(() => {
const now = Date.now();
Object.keys(partyLines).forEach((currentPartyLine) => {
const partyLine = partyLines[currentPartyLine];
if (partyLine.lastEvent && partyLine.clients.length > 0) {
broadcast(currentPartyLine, partyLine.lastEvent);
}
if (now - partyLine.lastActivity > 3600000) { // 1 hour in milliseconds
console.log(`DELETE: Deleting inactive party line ${currentPartyLine}`);
delete partyLines[currentPartyLine];
}
});
maintenanceService();
}, 30000);
// Start the server

View file

@ -0,0 +1,16 @@
import { partyLines } from "../stores/dataStore";
import { broadcast } from "./broadcastService";
export const maintenanceService = () => {
const now = Date.now();
Object.keys(partyLines).forEach((currentPartyLine) => {
const partyLine = partyLines[currentPartyLine];
if (partyLine.lastEvent && partyLine.clients.length > 0) {
broadcast(currentPartyLine, partyLine.lastEvent);
}
if (now - partyLine.lastActivity > 3600000) { // 1 hour in milliseconds
console.log(`DELETE: Deleting inactive party line ${currentPartyLine}`);
delete partyLines[currentPartyLine];
}
});
}