Repository: freeCodeCamp/freeCodeCamp
File: api/src/routes/protected/classroom.ts (TypeScript)

Code before:
import { FastifyPluginCallback } from 'fastify';
import { Type } from '@fastify/type-provider-typebox';
import { normalizeChallenges } from '../../utils/normalize.js';

/**
 * Fastify plugin for classroom-related protected routes.
 * Provides endpoint for retrieving user data for classrooms.
 * @param fastify - The Fastify instance.
 * @param _options - Plugin options (unused).
 * @param done - Callback to signal plugin registration is complete.
 */
export const classroomRoutes: FastifyPluginCallback = (
  fastify,
  _options,
  done
) => {
  // Endpoint to retrieve a user's ID from a user's email.
  fastify.post(
    '/api/protected/classroom/get-user-id',
    {
      schema: {
        body: Type.Object({
          email: Type.String({ format: 'email' })
        }),
        response: {
          200: Type.Object({
            userId: Type.String()
          }),
          404: Type.Object({
            error: Type.String()
          })
        }
      }
    },
    async (request, reply) => {
      const { email } = request.body as { email: string };

      try {
        // Find the user by email
        const user = await fastify.prisma.user.findFirst({
          where: { email },
          select: {
            id: true,
            isClassroomAccount: true
          }
        });

        if (!user || !user.isClassroomAccount) {

Review comment (suggestion):
```suggestion
          email: Type.String({ format: 'email', maxLength: 1024 })
```
This will need a max length because we don't want people sending arbitrarily large data and, if you use format, the schema will reject anything without it (since it large payloads make DoS attacks easier)

Code after:
import { FastifyPluginCallbackTypebox } from '@fastify/type-provider-typebox';
import {
  normalizeChallenges,
  NormalizedChallenge
} from '../../utils/normalize.js';
import * as schemas from '../../schemas/classroom/classroom.js';

/**
 * Fastify plugin for classroom-related protected routes.
 * Provides endpoint for retrieving user data for classrooms.
 * @param fastify - The Fastify instance.
 * @param _options - Plugin options (unused).
 * @param done - Callback to signal plugin registration is complete.
 */
export const classroomRoutes: FastifyPluginCallbackTypebox = (
  fastify,
  _options,
  done
) => {
  // Endpoint to retrieve a user's ID from a user's email.
  // If we send a 404 error here, it will stop the entire classroom process from working.
  // Instead, we indicate that the user was not found through a null response and continue.
  fastify.post(
    '/api/protected/classroom/get-user-id',
    {
      schema: schemas.classroomGetUserIdSchema
    },
    async (request, reply) => {
      const { email } = request.body;

      // Basic email validation - return empty userId for invalid emails
      const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
      if (!emailRegex.test(email)) {
        return reply.send({ userId: '' });
      }

      try {
        // Find the user by email
        const user = await fastify.prisma.user.findFirst({
          where: { email, isClassroomAccount: true },
          select: { id: true }
        });

        if (!user) {
          return reply.send({ userId: '' });
        }

        return reply.send({