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

Code before:
        return reply.send({
          message: 'flash.username-updated',
          type: 'success',
          variables: { username: newUsernameDisplay }
        });
      } catch (err) {
        logger.error(err);
        fastify.Sentry.captureException(err);
        void reply.code(500);
        await reply.send({ message: 'flash.wrong-updating', type: 'danger' });
      }
    }
  );

  fastify.put(
    '/update-my-about',
    {
      schema: schemas.updateMyAbout
    },
    async (req, reply) => {
      const logger = fastify.log.child({ req, res: reply });
      
      // Only validate picture if it's being changed
      if (req.body.picture !== undefined) {
        const currentUser = await fastify.prisma.user.findUnique({
          where: { id: req.user?.id },
          select: { picture: true }
        });
        
        // Only validate if the picture is actually different
        if (req.body.picture !== currentUser?.picture) {
          const pictureIsValid = isValidPictureUrl(req.body.picture);
          if (!pictureIsValid) {
            logger.warn(`Invalid picture URL: ${req.body.picture}`);
            void reply.code(400);
            return { message: 'flash.wrong-updating', type: 'danger' } as const;
          }
        }
      }

      try {
        // Build update data object, only including fields that are provided
        const updateData: {
          about?: string;
          name?: string;
          location?: string;
          picture?: string;
        } = {};
        
        if (req.body.about !== undefined) updateData.about = req.body.about;
        if (req.body.name !== undefined) updateData.name = req.body.name;

Review comment (bug):
This is where the issue was. My profile picture was previously valid, but a change to freeCodeCamp's API since I last logged in must have made it invalid.

Aside from this edge case, it doesn't make sense to revalidate unchanged data.

Code after:
        return reply.send({
          message: 'flash.username-updated',
          type: 'success',
          variables: { username: newUsernameDisplay }
        });
      } catch (err) {
        logger.error(err);
        fastify.Sentry.captureException(err);
        void reply.code(500);
        await reply.send({ message: 'flash.wrong-updating', type: 'danger' });
      }
    }
  );

  fastify.put(
    '/update-my-about',
    {
      schema: schemas.updateMyAbout
    },
    async (req, reply) => {
      const logger = fastify.log.child({ req, res: reply });

      // No need to validate if picture is being deleted.
      if (req.body.picture) {
        if (req.body.picture !== req.user!.picture) {
          if (!isValidPictureUrl(req.body.picture)) {
            logger.warn(`Invalid picture URL: ${req.body.picture}`);
            void reply.code(400);
            return { message: 'flash.wrong-updating', type: 'danger' } as const;
          }
        }
      }

      try {
        await fastify.prisma.user.update({
          where: { id: req.user?.id },
          data: {
            about: req.body.about,
            name: req.body.name,
            location: req.body.location,
            picture: req.body.picture
          }
        });

        return {
          message: 'flash.updated-about-me',
          type: 'success'
        } as const;
      } catch (err) {
        logger.error(err);
        fastify.Sentry.captureException(err);