fix(api): skip picture validation when unchanged (#64868)

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>
This commit is contained in:
Steven Boutcher
2026-01-14 02:05:35 -06:00
committed by GitHub
parent 0d9c476727
commit 0e1443f361
2 changed files with 79 additions and 5 deletions
+69
View File
@@ -991,6 +991,75 @@ Happy coding!
expect(response.body).toEqual(updateErrorResponse);
expect(response.statusCode).toEqual(400);
});
test('PUT allows updating location/about when picture is unchanged (even without extension)', async () => {
// Simulate a user who already has a GitHub avatar URL saved (e.g., from before strict validation)
const githubAvatarUrl =
'https://avatars0.githubusercontent.com/u/34585031?v=4';
await fastifyTestInstance.prisma.user.update({
where: { id: defaultUserId },
data: {
picture: githubAvatarUrl,
about: 'Initial about',
name: 'Test User',
location: 'Initial Location'
}
});
// Now update only location and about, keeping the same picture (no extension)
const updateResponse = await superPut('/update-my-about').send({
about: 'Updated about text',
name: 'Test User',
location: 'New Location',
picture: githubAvatarUrl // Same URL, no extension - should skip validation
});
expect(updateResponse.body).toEqual({
message: 'flash.updated-about-me',
type: 'success'
});
expect(updateResponse.statusCode).toEqual(200);
const user = await fastifyTestInstance?.prisma.user.findFirst({
where: { email: 'foo@bar.com' }
});
expect(user?.about).toEqual('Updated about text');
expect(user?.location).toEqual('New Location');
expect(user?.picture).toEqual(githubAvatarUrl);
});
test('PUT still validates picture when it is actually changed', async () => {
// Set initial valid picture
const validPictureUrl = 'https://example.com/avatar.png';
await superPut('/update-my-about').send({
about: 'Initial',
name: 'Test',
location: 'Location',
picture: validPictureUrl
});
// Try to change picture to invalid URL (no extension)
const updateResponse = await superPut('/update-my-about').send({
about: 'Initial',
name: 'Test',
location: 'Location',
picture: 'https://example.com/new-avatar' // Changed but invalid
});
expect(updateResponse.statusCode).toEqual(400);
expect(updateResponse.body).toEqual({
message: 'flash.wrong-updating',
type: 'danger'
});
// Verify picture wasn't updated
const user = await fastifyTestInstance?.prisma.user.findFirst({
where: { email: 'foo@bar.com' }
});
expect(user?.picture).toEqual(validPictureUrl);
});
});
describe('/update-my-honesty', () => {
+10 -5
View File
@@ -523,11 +523,16 @@ ${isLinkSentWithinLimitTTL}`
},
async (req, reply) => {
const logger = fastify.log.child({ req, res: reply });
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;
// 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 {