Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import nodePlugin from 'eslint-plugin-n';
import securityPlugin from 'eslint-plugin-security';
import sonarjs from 'eslint-plugin-sonarjs';
import globals from 'globals';

export default tseslint.config(
Expand All @@ -22,6 +23,7 @@ export default tseslint.config(
js.configs.recommended,
nodePlugin.configs['flat/recommended-module'],
securityPlugin.configs.recommended,
sonarjs.configs.recommended,
{
files: ['**/*.ts'],
extends: [...tseslint.configs.recommendedTypeChecked],
Expand Down Expand Up @@ -63,4 +65,14 @@ export default tseslint.config(
'max-len': ['error', { code: 150 }],
},
},
{
// Test-only override: deeply-nested arrow chains are the clearest way to
// build mock factories (e.g. socketcluster's receiver/consumer/next chain),
// and refactoring them into named helpers reduces readability rather than
// improving it. Keep the rule active for src/.
files: ['test/**/*.ts'],
rules: {
'sonarjs/no-nested-functions': 'off',
},
},
);
125 changes: 110 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
"eslint": "^10.2.1",
"eslint-plugin-n": "^17.24.0",
"eslint-plugin-security": "^4.0.0",
"eslint-plugin-sonarjs": "^4.0.3",
"globals": "^17.5.0",
"supertest": "^7.2.2",
"typescript-eslint": "^8.59.1",
Expand Down
62 changes: 34 additions & 28 deletions src/AgController/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ class AgController {
(async () => {
let disconnect: { value: undefined; done: any; };
const dConsumer = client.listener('disconnect').createConsumer();
while (true) { // eslint-disable-line no-constant-condition
disconnect = await dConsumer.next();// eslint-disable-line no-await-in-loop
while (true) {
disconnect = await dConsumer.next();
clearInterval(interval);
if (disconnect.value !== undefined) {
const index = this.clients.indexOf(client.id);
Expand All @@ -55,6 +55,9 @@ class AgController {

sendPulse(client:IClient):void {
const interval = setInterval(() => {
// sonarjs/pseudo-random: this is a non-security pulse heartbeat for clients
// (an arbitrary 0-4 number transmitted every second). Math.random is fine here.
// eslint-disable-next-line sonarjs/pseudo-random
client.socket.transmit('pulse', { number: Math.floor(Math.random() * 5) });
}, 1000);
debug(`num clients: ${this.clients.length}`);
Expand Down Expand Up @@ -89,14 +92,17 @@ class AgController {
(async () => {
let receiver: { value: number; done: any; };
const rConsumer = client.socket.receiver('initial message').createConsumer();
while (true) { // eslint-disable-line no-constant-condition
receiver = await rConsumer.next();// eslint-disable-line no-await-in-loop
while (true) {
receiver = await rConsumer.next();
debug(`received initial message: ${receiver.value}`);
if (receiver.value === 123) {
await this.sendTours(client);// eslint-disable-line no-await-in-loop
await this.sendBooks(client);// eslint-disable-line no-await-in-loop
} else break;
/* istanbul ignore else */if (receiver.done) break;
await this.sendTours(client);
await this.sendBooks(client);
} else {
break;
}
/* istanbul ignore else */
if (receiver.done) break;
}
})();
}
Expand All @@ -117,14 +123,14 @@ class AgController {
(async () => {
let receiver: { value: { token: string; image: any }, done: any; };
const rConsumer = client.socket.receiver('newImage').createConsumer();
while (true) { // eslint-disable-line no-constant-condition
receiver = await rConsumer.next();// eslint-disable-line no-await-in-loop
while (true) {
receiver = await rConsumer.next();
debug(`received newImage message: ${JSON.stringify(receiver.value)}`);
if (!receiver.value) break;
if (typeof receiver.value.token === 'string'
&& typeof receiver.value.image.title === 'string' && typeof receiver.value.image.url === 'string'
) {
await this.handleImage('createDocs', receiver.value.image, 'imageCreated');// eslint-disable-line no-await-in-loop
await this.handleImage('createDocs', receiver.value.image, 'imageCreated');
}
/* istanbul ignore else */if (receiver.done) break;
}
Expand All @@ -138,10 +144,10 @@ class AgController {
):Promise<string> {
const { editPic, token } = data;
const {
// eslint-disable-next-line @typescript-eslint/naming-convention
_id, title, url, comments,
} = editPic;
let r: any;// eslint-disable-next-line security/detect-object-injection
let r: any;
if (typeof token !== 'string') throw new Error('invalid token');
try { r = await this.bookController.findByIdAndUpdate(_id, { title, url, comments }); } catch (e) {
const eMessage = (e as Error).message;
Expand All @@ -157,12 +163,12 @@ class AgController {
(async () => {
let receiver: { value: { data: string; token: string; }; done: any; };
const rConsumer = client.socket.receiver('deleteImage').createConsumer();
while (true) { // eslint-disable-line no-constant-condition
receiver = await rConsumer.next();// eslint-disable-line no-await-in-loop
while (true) {
receiver = await rConsumer.next();
debug(`received deleteImage message: ${JSON.stringify(receiver.value)}`);
if (!receiver.value) break;
if (typeof receiver.value.token === 'string' && typeof receiver.value.data === 'string') {
await this.handleImage('deleteById', receiver.value.data, 'imageDeleted');// eslint-disable-line no-await-in-loop
await this.handleImage('deleteById', receiver.value.data, 'imageDeleted');
}
/* istanbul ignore else */if (receiver.done) break;
}
Expand All @@ -174,8 +180,8 @@ class AgController {
let receiver: { value: { token: string;
tour: { datetime: Date; venue: string; city:string, usState: string }; }; done: any; };
const rConsumer = client.socket.receiver('newTour').createConsumer();
while (true) { // eslint-disable-line no-constant-condition
receiver = await rConsumer.next();// eslint-disable-line no-await-in-loop
while (true) {
receiver = await rConsumer.next();
let decoded, user, goodRoles;
if (!receiver.value) break;
try {
Expand All @@ -191,7 +197,7 @@ class AgController {
}
if (receiver.value.tour.datetime && receiver.value.tour.city
&& receiver.value.tour.usState && receiver.value.tour.venue) {
await utils.handleTour(// eslint-disable-line no-await-in-loop
await utils.handleTour(
'createDocs',
receiver.value.tour,
'tourCreated',
Expand All @@ -214,11 +220,11 @@ class AgController {
(async () => {
let receiver: { value: { tour:any; token: any; }; done: any; };
const rConsumer = client.socket.receiver('deleteTour').createConsumer();
while (true) { // eslint-disable-line no-constant-condition
receiver = await rConsumer.next();// eslint-disable-line no-await-in-loop
while (true) {
receiver = await rConsumer.next();
debug(`received deleteTour message: ${JSON.stringify(receiver.value)}`);
if (!receiver.value) break;
await utils.removeTour(receiver, client, this.tourController, this.server);// eslint-disable-line no-await-in-loop
await utils.removeTour(receiver, client, this.tourController, this.server);
/* istanbul ignore else */if (receiver.done) break;
}
})();
Expand All @@ -227,7 +233,7 @@ class AgController {
async updateTour(
data: { tourId: mongoose.Types.ObjectId; tour: Record<string, unknown>; },
):Promise<string> {
let r: any;// eslint-disable-next-line security/detect-object-injection
let r: any;
try {
const { tourId, tour } = data;
if (!tour.venue || !tour.datetime || !tour.city || !tour.usState) throw new Error('Invalid gig data');
Expand All @@ -245,15 +251,15 @@ class AgController {
(async () => {
let receiver: { value:any; done: any; };
const rConsumer = client.socket.receiver(action).createConsumer();
while (true) { // eslint-disable-line no-constant-condition
receiver = await rConsumer.next();// eslint-disable-line no-await-in-loop
while (true) {
receiver = await rConsumer.next();
const obj = JSON.stringify(receiver.value);
debug(`received ${action} message: ${obj}`);
if (!receiver.value) break;
if (typeof receiver.value.token === 'string') {
// eslint-disable-next-line security/detect-object-injection
if (action === 'editTour') await this.updateTour(receiver.value);// eslint-disable-line no-await-in-loop
// eslint-disable-next-line no-await-in-loop
if (action === 'editTour') await this.updateTour(receiver.value);
else await this.updateImage(receiver.value, client);
}
/* istanbul ignore else */if (receiver.done) break;
Expand Down
Loading
Loading