diff --git a/packages/server/src/bootstrap.ts b/packages/server/src/bootstrap.ts index 14b826e76..74d3ad797 100644 --- a/packages/server/src/bootstrap.ts +++ b/packages/server/src/bootstrap.ts @@ -32,7 +32,6 @@ export async function bootstrap(hot: any): Promise { ); } - addGlobalsToApp(app); app.setGlobalPrefix('api/v1'); app.use(morgan('dev')); app.use(bodyParser.json({ limit: '50mb' })); @@ -69,9 +68,26 @@ export async function bootstrap(hot: any): Promise { // Global settings that should be true in prod and in integration tests export function addGlobalsToApp(app: INestApplication): void { app.useGlobalPipes( + // Y'know all of our classes with decorators inside common/index.ts? + // Those are known as DTOs and we put them on our endpoints, + // and this ValidationPipe will validate the bodies so that whatever the frontend sends + // will match the DTOs. This prevents the frontend from sending bad data to the backend (very very important). new ValidationPipe({ + // This will turn our DTOs into essentially a "whitelist", where any properties + // that are in the object passed to the endpoint but are not inside the DTO are not allowed. + // By default, this will DROP any properties that are not in the DTO (unless forbidNonWhitelisted is true). whitelist: true, - forbidNonWhitelisted: true, + // This controls whether or not we want to throw an error to the frontend if the body + // has properties that are not in the DTO. + // Having this false may result in some hidden errors, where you may try to pass something + // to the backend just for it to mysteriously disappear. + // But having this true may result in actual annoying errors for our users if for some reason + // we were to mess up our frontend and call our backend with bad data. + // So there's tradeoffs either way. + forbidNonWhitelisted: false, + // This will automatically transform the body to the DTO types. + // Over HTTP, the whole body and properties are a string so this will automatically + // transform them into numbers, booleans, other objects, etc. transform: true, }), ); diff --git a/packages/server/test/question.integration.ts b/packages/server/test/question.integration.ts index 2acdc0afa..316b04434 100644 --- a/packages/server/test/question.integration.ts +++ b/packages/server/test/question.integration.ts @@ -1081,7 +1081,11 @@ describe('Question Integration', () => { name: ta.name, }, }) - .expect(400); + .expect(200); // the taHelped should have gotten dropped automatically + + // fetch the question from the DB to make sure it wasn't updated + const question = await QuestionModel.findOne({ where: { id: q.id } }); + expect(question.taHelped).toBeUndefined(); }); it('PATCH status to helping as student not allowed', async () => { const course = await CourseFactory.create();