diff --git a/api/src/app.ts b/api/src/app.ts index fec71629751..1596468b2ca 100644 --- a/api/src/app.ts +++ b/api/src/app.ts @@ -38,7 +38,8 @@ import { FCC_ENABLE_DEV_LOGIN_MODE, FCC_ENABLE_SWAGGER_UI, FCC_ENABLE_SHADOW_CAPTURE, - FCC_ENABLE_EXAM_ENVIRONMENT + FCC_ENABLE_EXAM_ENVIRONMENT, + FCC_ENABLE_SENTRY_ROUTES } from './utils/env'; import { isObjectID } from './utils/validation'; import { @@ -198,6 +199,10 @@ export const build = async ( void fastify.register(examEnvironmentOpenRoutes); } + if (FCC_ENABLE_SENTRY_ROUTES) { + void fastify.register(publicRoutes.sentryRoutes); + } + void fastify.register(publicRoutes.chargeStripeRoute); void fastify.register(publicRoutes.signoutRoute); void fastify.register(publicRoutes.emailSubscribtionRoutes); diff --git a/api/src/routes/public/index.ts b/api/src/routes/public/index.ts index 95ad20bb343..7bbb12f5fd1 100644 --- a/api/src/routes/public/index.ts +++ b/api/src/routes/public/index.ts @@ -8,3 +8,4 @@ export * from './email-subscription'; export * from './signout'; export * from './status'; export * from './user'; +export * from './sentry'; diff --git a/api/src/routes/public/sentry.ts b/api/src/routes/public/sentry.ts new file mode 100644 index 00000000000..60e70705450 --- /dev/null +++ b/api/src/routes/public/sentry.ts @@ -0,0 +1,41 @@ +/* eslint-disable jsdoc/require-returns, jsdoc/require-param */ +import { type FastifyPluginCallbackTypebox } from '@fastify/type-provider-typebox'; +import { type FastifyInstance, type FastifyReply } from 'fastify'; + +import { UpdateReqType } from '../../utils'; +import * as schemas from '../../schemas'; + +/** + * Plugin for Sentry-related endpoints. + * + * @param fastify The Fastify instance. + * @param _options Options passed to the plugin via `fastify.register(plugin, + * options)`. + * @param done The callback to signal that the plugin is ready. + */ +export const sentryRoutes: FastifyPluginCallbackTypebox = ( + fastify, + _options, + done +) => { + fastify.post( + '/sentry/event', + { + schema: schemas.sentryPostEvent + }, + postSentryEventHandler + ); + + done(); +}; + +/** + * Creates a new event in Sentry. + */ +function postSentryEventHandler( + this: FastifyInstance, + req: UpdateReqType, + _reply: FastifyReply +) { + throw new Error(`Sentry Test: ${req.body.text}`); +} diff --git a/api/src/schemas.ts b/api/src/schemas.ts index 78ac4034d22..8afb7f295ed 100644 --- a/api/src/schemas.ts +++ b/api/src/schemas.ts @@ -41,3 +41,4 @@ export { reportUser } from './schemas/user/report-user'; export { resetMyProgress } from './schemas/user/reset-my-progress'; export { submitSurvey } from './schemas/user/submit-survey'; export { userExamEnvironmentToken } from './schemas/user/exam-environment-token'; +export { sentryPostEvent } from './schemas/sentry/event'; diff --git a/api/src/schemas/sentry/event.ts b/api/src/schemas/sentry/event.ts new file mode 100644 index 00000000000..fc5150ccd25 --- /dev/null +++ b/api/src/schemas/sentry/event.ts @@ -0,0 +1,13 @@ +import { Type } from '@fastify/type-provider-typebox'; + +export const sentryPostEvent = { + body: Type.Object({ + text: Type.String() + }), + response: { + 500: Type.Object({ + message: Type.Literal('flash.generic-error'), + type: Type.Literal('danger') + }) + } +}; diff --git a/api/src/utils/env.ts b/api/src/utils/env.ts index 52d2316ad99..813df7a561c 100644 --- a/api/src/utils/env.ts +++ b/api/src/utils/env.ts @@ -135,6 +135,8 @@ export const FCC_ENABLE_SHADOW_CAPTURE = process.env.FCC_ENABLE_SHADOW_CAPTURE === 'true'; export const FCC_ENABLE_EXAM_ENVIRONMENT = process.env.FCC_ENABLE_EXAM_ENVIRONMENT === 'true'; +export const FCC_ENABLE_SENTRY_ROUTES = + process.env.FCC_ENABLE_SENTRY_ROUTES === 'true'; export const SENTRY_DSN = process.env.SENTRY_DSN === 'dsn_from_sentry_dashboard' ? '' diff --git a/sample.env b/sample.env index 1150fff9a5a..9eaca7eb8c6 100644 --- a/sample.env +++ b/sample.env @@ -70,6 +70,7 @@ FCC_ENABLE_SWAGGER_UI=true FCC_ENABLE_DEV_LOGIN_MODE=true FCC_ENABLE_SHADOW_CAPTURE=false FCC_ENABLE_EXAM_ENVIRONMENT=false +FCC_ENABLE_SENTRY_ROUTES=false # Email # use ses in production