mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-09-24 23:01:18 +08:00
feat(api): add update-my-about endpoint (#50334)
Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com> Co-authored-by: Sem Bauke <semboot699@gmail.com>
This commit is contained in:
co-authored by
Oliver Eyton-Williams
Sem Bauke
parent
5331994dbe
commit
01ae9d3561
@@ -0,0 +1,14 @@
|
||||
import { isPictureWithProtocol } from './settings';
|
||||
|
||||
describe('url has protocol', () => {
|
||||
test('Valid protocol', () => {
|
||||
expect(isPictureWithProtocol('https://www.example.com/')).toEqual(true);
|
||||
expect(isPictureWithProtocol('http://www.example.com/')).toEqual(true);
|
||||
});
|
||||
|
||||
test('Invalid protocol', () => {
|
||||
expect(isPictureWithProtocol('htps://www.example.com/')).toEqual(false);
|
||||
expect(isPictureWithProtocol('tp://www.example.com/')).toEqual(false);
|
||||
expect(isPictureWithProtocol('www.example.com/')).toEqual(false);
|
||||
});
|
||||
});
|
||||
@@ -465,6 +465,57 @@ describe('settingRoutes', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('/update-my-about', () => {
|
||||
test('PUT updates the values in about settings', async () => {
|
||||
const response = await superRequest('/update-my-about', {
|
||||
method: 'PUT',
|
||||
setCookies
|
||||
}).send({
|
||||
about: 'Teacher at freeCodeCamp',
|
||||
name: 'Quincy Larson',
|
||||
location: 'USA',
|
||||
picture:
|
||||
'https://cdn.freecodecamp.org/platform/english/images/quincy-larson-signature.svg'
|
||||
});
|
||||
|
||||
expect(response.body).toEqual({
|
||||
message: 'flash.updated-about-me',
|
||||
type: 'success'
|
||||
});
|
||||
|
||||
const user = await fastifyTestInstance?.prisma.user.findFirst({
|
||||
where: { email: 'foo@bar.com' }
|
||||
});
|
||||
|
||||
expect(user?.about).toEqual('Teacher at freeCodeCamp');
|
||||
expect(user?.name).toEqual('Quincy Larson');
|
||||
expect(user?.location).toEqual('USA');
|
||||
expect(user?.picture).toEqual(
|
||||
'https://cdn.freecodecamp.org/platform/english/images/quincy-larson-signature.svg'
|
||||
);
|
||||
expect(response.statusCode).toEqual(200);
|
||||
});
|
||||
|
||||
test('PUT updates the values in about settings without image', async () => {
|
||||
const response = await superRequest('/update-my-about', {
|
||||
method: 'PUT',
|
||||
setCookies
|
||||
}).send({
|
||||
about: 'Teacher at freeCodeCamp',
|
||||
name: 'Quincy Larson',
|
||||
location: 'USA',
|
||||
// `new URL` throws if the image isn't a URL, this checks if it doesn't throw.
|
||||
picture: 'invalid'
|
||||
});
|
||||
|
||||
expect(response.body).toEqual({
|
||||
message: 'flash.updated-about-me',
|
||||
type: 'success'
|
||||
});
|
||||
expect(response.statusCode).toEqual(200);
|
||||
});
|
||||
});
|
||||
|
||||
describe('/update-my-honesty', () => {
|
||||
test('PUT returns 200 status code with "success" message', async () => {
|
||||
const response = await superRequest('/update-my-honesty', {
|
||||
|
||||
@@ -5,6 +5,16 @@ import { isValidUsername } from '../../../utils/validate';
|
||||
import { blocklistedUsernames } from '../../../config/constants.js';
|
||||
import { schemas } from '../schemas';
|
||||
|
||||
export const isPictureWithProtocol = (picture?: string): boolean => {
|
||||
if (!picture) return false;
|
||||
try {
|
||||
const url = new URL(picture);
|
||||
return url.protocol == 'http:' || url.protocol == 'https:';
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const settingRoutes: FastifyPluginCallbackTypebox = (
|
||||
fastify,
|
||||
_options,
|
||||
@@ -196,6 +206,36 @@ export const settingRoutes: FastifyPluginCallbackTypebox = (
|
||||
}
|
||||
}
|
||||
);
|
||||
fastify.put(
|
||||
'/update-my-about',
|
||||
{
|
||||
schema: schemas.updateMyAbout
|
||||
},
|
||||
async (req, reply) => {
|
||||
const hasProtocol = isPictureWithProtocol(req.body.picture);
|
||||
|
||||
try {
|
||||
await fastify.prisma.user.update({
|
||||
where: { id: req.session.user.id },
|
||||
data: {
|
||||
about: req.body.about,
|
||||
name: req.body.name,
|
||||
location: req.body.location,
|
||||
...(hasProtocol && { picture: req.body.picture })
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
message: 'flash.updated-about-me',
|
||||
type: 'success'
|
||||
} as const;
|
||||
} catch (err) {
|
||||
fastify.log.error(err);
|
||||
void reply.code(500);
|
||||
return { message: 'flash.wrong-updating', type: 'danger' } as const;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
fastify.put(
|
||||
'/update-my-keyboard-shortcuts',
|
||||
|
||||
@@ -128,6 +128,24 @@ export const schemas = {
|
||||
})
|
||||
}
|
||||
},
|
||||
updateMyAbout: {
|
||||
body: Type.Object({
|
||||
about: Type.Optional(Type.String()),
|
||||
name: Type.Optional(Type.String()),
|
||||
picture: Type.Optional(Type.String()),
|
||||
location: Type.Optional(Type.String())
|
||||
}),
|
||||
response: {
|
||||
200: Type.Object({
|
||||
message: Type.Literal('flash.updated-about-me'),
|
||||
type: Type.Literal('success')
|
||||
}),
|
||||
500: Type.Object({
|
||||
message: Type.Literal('flash.wrong-updating'),
|
||||
type: Type.Literal('danger')
|
||||
})
|
||||
}
|
||||
},
|
||||
updateMyPrivacyTerms: {
|
||||
body: Type.Object({
|
||||
quincyEmails: Type.Boolean()
|
||||
|
||||
Reference in New Issue
Block a user