fix(api): use generic error message if CSRF error (#55264)

This commit is contained in:
Oliver Eyton-Williams
2024-06-27 10:47:23 +02:00
committed by GitHub
parent 512547e76c
commit a22e90c10d
20 changed files with 91 additions and 61 deletions
+4 -1
View File
@@ -105,7 +105,10 @@ export const build = async (
// test environments)
skipInit: !SENTRY_DSN,
errorResponse: (error, _request, reply) => {
if (reply.statusCode === 500) {
const isCSRFError =
error.code === 'FST_CSRF_INVALID_TOKEN' ||
error.code === 'FST_CSRF_MISSING_SECRET';
if (reply.statusCode === 500 || isCSRFError) {
void reply.send({
message: 'flash.generic-error',
type: 'danger'
+2 -3
View File
@@ -396,8 +396,7 @@ export const challengeRoutes: FastifyPluginCallbackTypebox = (
!multifileCertProjectIds.includes(challengeId) &&
!multifilePythonCertProjectIds.includes(challengeId)
) {
void reply.code(403);
return 'That challenge type is not saveable.';
void reply.code(403).send('That challenge type is not saveable.');
}
const userSavedChallenges = saveUserChallengeData(
@@ -413,7 +412,7 @@ export const challengeRoutes: FastifyPluginCallbackTypebox = (
}
});
return { savedChallenges: userSavedChallenges };
void reply.send({ savedChallenges: userSavedChallenges });
}
);
+4 -8
View File
@@ -62,10 +62,8 @@ describe('settingRoutes', () => {
});
expect(response.body).toEqual({
code: 'FST_CSRF_MISSING_SECRET',
error: 'Forbidden',
message: 'Missing csrf secret',
statusCode: 403
message: 'flash.generic-error',
type: 'danger'
});
expect(response.statusCode).toEqual(403);
});
@@ -76,10 +74,8 @@ describe('settingRoutes', () => {
}).set('Cookie', ['_csrf=foo', 'csrf-token=bar']);
expect(response.body).toEqual({
code: 'FST_CSRF_INVALID_TOKEN',
error: 'Forbidden',
message: 'Invalid csrf token',
statusCode: 403
message: 'flash.generic-error',
type: 'danger'
});
expect(response.statusCode).toEqual(403);
});
+2 -2
View File
@@ -1,6 +1,6 @@
import { Type } from '@fastify/type-provider-typebox';
import { Certification } from '../../../../shared/config/certification-settings';
import { generic500 } from '../types';
import { genericError } from '../types';
export const certSlug = {
params: Type.Object({
@@ -120,6 +120,6 @@ export const certSlug = {
})
)
}),
500: generic500
default: genericError
}
};
@@ -1,5 +1,5 @@
import { Type } from '@fastify/type-provider-typebox';
import { generic500, isCertMap } from '../types';
import { genericError, isCertMap } from '../types';
export const certificateVerify = {
// TODO(POST_MVP): Remove partial validation from route for schema validation
@@ -126,7 +126,8 @@ export const certificateVerify = {
type: Type.Literal('danger'),
message: Type.Literal('flash.went-wrong')
}),
generic500
])
genericError
]),
default: genericError
}
};
@@ -1,5 +1,5 @@
import { Type } from '@fastify/type-provider-typebox';
import { generic500 } from '../types';
import { genericError } from '../types';
export const backendChallengeCompleted = {
body: Type.Object({
@@ -17,6 +17,6 @@ export const backendChallengeCompleted = {
'That does not appear to be a valid challenge submission.'
)
}),
500: generic500
default: genericError
}
};
@@ -1,5 +1,5 @@
import { Type } from '@fastify/type-provider-typebox';
import { generic500 } from '../types';
import { genericError } from '../types';
export const coderoadChallengeCompleted = {
body: Type.Object({
@@ -15,6 +15,6 @@ export const coderoadChallengeCompleted = {
type: Type.Literal('error'),
msg: Type.String()
}),
500: generic500
default: genericError
}
};
@@ -1,5 +1,5 @@
import { Type } from '@fastify/type-provider-typebox';
import { examResults } from '../types';
import { examResults, genericError } from '../types';
export const examChallengeCompleted = {
body: Type.Object({
@@ -30,9 +30,12 @@ export const examChallengeCompleted = {
400: Type.Object({
error: Type.String()
}),
403: Type.Object({
error: Type.String()
}),
403: Type.Union([
Type.Object({
error: Type.String()
}),
genericError
]),
500: Type.Object({
error: Type.String()
})
+7 -3
View File
@@ -1,4 +1,5 @@
import { Type } from '@fastify/type-provider-typebox';
import { genericError } from '../types';
export const exam = {
params: Type.Object({
@@ -27,9 +28,12 @@ export const exam = {
400: Type.Object({
error: Type.String()
}),
403: Type.Object({
error: Type.String()
}),
403: Type.Union([
Type.Object({
error: Type.String()
}),
genericError
]),
500: Type.Object({
error: Type.String()
})
@@ -1,5 +1,5 @@
import { Type } from '@fastify/type-provider-typebox';
import { generic500, savedChallenge } from '../types';
import { genericError, savedChallenge } from '../types';
export const modernChallengeCompleted = {
body: Type.Object({
@@ -30,6 +30,6 @@ export const modernChallengeCompleted = {
'That does not appear to be a valid challenge submission.'
)
}),
500: generic500
default: genericError
}
};
+16 -11
View File
@@ -1,5 +1,5 @@
import { Type } from '@fastify/type-provider-typebox';
import { generic500 } from '../types';
import { genericError } from '../types';
export const projectCompleted = {
body: Type.Object({
@@ -28,15 +28,20 @@ export const projectCompleted = {
)
])
}),
403: Type.Object({
type: Type.Literal('error'),
message: Type.Union([
Type.Literal(
'You have to complete the project before you can submit a URL.'
),
Type.Literal('That does not appear to be a valid challenge submission.')
])
}),
500: generic500
403: Type.Union([
Type.Object({
type: Type.Literal('error'),
message: Type.Union([
Type.Literal(
'You have to complete the project before you can submit a URL.'
),
Type.Literal(
'That does not appear to be a valid challenge submission.'
)
])
}),
genericError
]),
default: genericError
}
};
+12 -3
View File
@@ -1,5 +1,5 @@
import { Type } from '@fastify/type-provider-typebox';
import { file, generic500, savedChallenge } from '../types';
import { file, genericError, savedChallenge } from '../types';
export const saveChallenge = {
body: Type.Object({
@@ -14,7 +14,16 @@ export const saveChallenge = {
200: Type.Object({
savedChallenges: Type.Array(savedChallenge)
}),
403: Type.Literal('That challenge type is not saveable.'),
500: generic500
400: Type.Object({
message: Type.Literal(
'That does not appear to be a valid challenge submission.'
),
type: Type.Literal('error')
}),
403: Type.Union([
Type.Literal('That challenge type is not saveable.'),
genericError
]),
default: genericError
}
};
@@ -1,4 +1,5 @@
import { Type } from '@fastify/type-provider-typebox';
import { genericError } from '../types';
export const updateMyClassroomMode = {
body: Type.Object({
@@ -9,9 +10,12 @@ export const updateMyClassroomMode = {
message: Type.Literal('flash.classroom-mode-updated'),
type: Type.Literal('success')
}),
403: Type.Object({
message: Type.Literal('flash.wrong-updating'),
type: Type.Literal('danger')
})
403: Type.Union([
Type.Object({
message: Type.Literal('flash.wrong-updating'),
type: Type.Literal('danger')
}),
genericError
])
}
};
+1 -1
View File
@@ -1,6 +1,6 @@
import { Type } from '@fastify/type-provider-typebox';
export const generic500 = Type.Object({
export const genericError = Type.Object({
message: Type.Literal('flash.generic-error'),
type: Type.Literal('danger')
});
+2 -2
View File
@@ -1,9 +1,9 @@
import { Type } from '@fastify/type-provider-typebox';
import { generic500 } from '../types';
import { genericError } from '../types';
export const deleteMyAccount = {
response: {
200: Type.Object({}),
500: generic500
default: genericError
}
};
+2 -2
View File
@@ -1,5 +1,5 @@
import { Type } from '@fastify/type-provider-typebox';
import { generic500 } from '../types';
import { genericError } from '../types';
export const deleteUserToken = {
response: {
@@ -10,6 +10,6 @@ export const deleteUserToken = {
message: Type.Literal('userToken not found'),
type: Type.Literal('info')
}),
500: generic500
default: genericError
}
};
+8 -4
View File
@@ -1,4 +1,5 @@
import { Type } from '@fastify/type-provider-typebox';
import { genericError } from '../types';
export const postMsUsername = {
body: Type.Object({
@@ -16,10 +17,13 @@ export const postMsUsername = {
type: Type.Literal('error'),
message: Type.Literal('flash.ms.transcript.link-err-2')
}),
403: Type.Object({
type: Type.Literal('error'),
message: Type.Literal('flash.ms.transcript.link-err-4')
}),
403: Type.Union([
Type.Object({
type: Type.Literal('error'),
message: Type.Literal('flash.ms.transcript.link-err-4')
}),
genericError
]),
500: Type.Union([
Type.Object({
type: Type.Literal('error'),
+2 -2
View File
@@ -1,5 +1,5 @@
import { Type } from '@fastify/type-provider-typebox';
import { generic500 } from '../types';
import { genericError } from '../types';
export const reportUser = {
body: Type.Object({
@@ -18,6 +18,6 @@ export const reportUser = {
type: Type.Literal('danger'),
message: Type.Literal('flash.provide-username')
}),
500: generic500
default: genericError
}
};
+2 -2
View File
@@ -1,9 +1,9 @@
import { Type } from '@fastify/type-provider-typebox';
import { generic500 } from '../types';
import { genericError } from '../types';
export const resetMyProgress = {
response: {
200: Type.Object({}),
500: generic500
default: genericError
}
};
+2
View File
@@ -34,6 +34,8 @@ export const formatProjectCompletedValidation = (
): FormattedError => {
const error = getError(errors);
// TODO: split this into two functions. There's no need for it to handle both
// /project-completed and /save-challenge
return error.instancePath === '' &&
error.params.missingProperty === 'solution'
? {