mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
fix(api): generate required properties for new users (#51822)
This commit is contained in:
committed by
GitHub
parent
fac5c52be2
commit
948b7c52c2
+3
-4
@@ -1,7 +1,7 @@
|
||||
import request from 'supertest';
|
||||
|
||||
import { build } from './src/app';
|
||||
import { defaultUser } from './src/utils/default-user';
|
||||
import { createUserInput } from './src/utils/create-user';
|
||||
|
||||
type FastifyTestInstance = Awaited<ReturnType<typeof build>>;
|
||||
|
||||
@@ -84,9 +84,8 @@ export async function devLogin(): Promise<string[]> {
|
||||
|
||||
await fastifyTestInstance.prisma.user.create({
|
||||
data: {
|
||||
...defaultUser,
|
||||
id: defaultUserId,
|
||||
email: defaultUserEmail
|
||||
...createUserInput(defaultUserEmail),
|
||||
id: defaultUserId
|
||||
}
|
||||
});
|
||||
const res = await superRequest('/auth/dev-callback', { method: 'GET' });
|
||||
|
||||
@@ -1,15 +1,95 @@
|
||||
import { setupServer, superRequest } from '../../jest.utils';
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import { defaultUserEmail, setupServer, superRequest } from '../../jest.utils';
|
||||
|
||||
describe('dev login', () => {
|
||||
setupServer();
|
||||
it('should create an account if one does not exist', async () => {
|
||||
beforeEach(async () => {
|
||||
await fastifyTestInstance.prisma.user.deleteMany({
|
||||
where: { email: 'foo@bar.com' }
|
||||
where: { email: defaultUserEmail }
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await fastifyTestInstance.prisma.user.deleteMany({
|
||||
where: { email: defaultUserEmail }
|
||||
});
|
||||
});
|
||||
|
||||
it('should create an account if one does not exist', async () => {
|
||||
const res = await superRequest('/auth/dev-callback', { method: 'GET' });
|
||||
|
||||
const count = await fastifyTestInstance.prisma.user.count({
|
||||
where: { email: defaultUserEmail }
|
||||
});
|
||||
|
||||
const res = await superRequest('/auth/dev-callback', { method: 'GET' });
|
||||
expect(count).toBe(1);
|
||||
|
||||
expect(res.body).toStrictEqual({ statusCode: 200 });
|
||||
expect(res.status).toBe(200);
|
||||
});
|
||||
|
||||
it('should populate the user with the correct data', async () => {
|
||||
const uuidRe = /^[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$/;
|
||||
const fccUuidRe = /^fcc-[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$/;
|
||||
|
||||
await superRequest('/auth/dev-callback', { method: 'GET' });
|
||||
const user = await fastifyTestInstance.prisma.user.findFirstOrThrow({
|
||||
where: { email: defaultUserEmail }
|
||||
});
|
||||
|
||||
expect(user).toMatchObject({
|
||||
about: '',
|
||||
acceptedPrivacyTerms: false,
|
||||
completedChallenges: [],
|
||||
currentChallengeId: '',
|
||||
email: defaultUserEmail,
|
||||
emailVerified: true,
|
||||
externalId: expect.stringMatching(uuidRe),
|
||||
is2018DataVisCert: false,
|
||||
is2018FullStackCert: false,
|
||||
isApisMicroservicesCert: false,
|
||||
isBackEndCert: false,
|
||||
isBanned: false,
|
||||
isCheater: false,
|
||||
isDataAnalysisPyCertV7: false,
|
||||
isDataVisCert: false,
|
||||
isDonating: false,
|
||||
isFrontEndCert: false,
|
||||
isFrontEndLibsCert: false,
|
||||
isFullStackCert: false,
|
||||
isHonest: false,
|
||||
isInfosecCertV7: false,
|
||||
isInfosecQaCert: false,
|
||||
isJsAlgoDataStructCert: false,
|
||||
isMachineLearningPyCertV7: false,
|
||||
isQaCertV7: false,
|
||||
isRelationalDatabaseCertV8: false,
|
||||
isCollegeAlgebraPyCertV8: false,
|
||||
isRespWebDesignCert: false,
|
||||
isSciCompPyCertV7: false,
|
||||
keyboardShortcuts: false,
|
||||
location: '',
|
||||
name: '',
|
||||
unsubscribeId: '',
|
||||
picture: '',
|
||||
profileUI: {
|
||||
isLocked: false,
|
||||
showAbout: false,
|
||||
showCerts: false,
|
||||
showDonation: false,
|
||||
showHeatMap: false,
|
||||
showLocation: false,
|
||||
showName: false,
|
||||
showPoints: false,
|
||||
showPortfolio: false,
|
||||
showTimeLine: false
|
||||
},
|
||||
progressTimestamps: [],
|
||||
sendQuincyEmail: false,
|
||||
theme: 'default',
|
||||
username: expect.stringMatching(fccUuidRe),
|
||||
usernameDisplay: expect.stringMatching(fccUuidRe)
|
||||
});
|
||||
expect(user.username).toBe(user.usernameDisplay);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
FastifyRequest
|
||||
} from 'fastify';
|
||||
|
||||
import { defaultUser } from '../utils/default-user';
|
||||
import { createUserInput } from '../utils/create-user';
|
||||
import { AUTH0_DOMAIN, HOME_LOCATION } from '../utils/env';
|
||||
|
||||
declare module 'fastify' {
|
||||
@@ -41,7 +41,7 @@ const findOrCreateUser = async (fastify: FastifyInstance, email: string) => {
|
||||
return (
|
||||
existingUser ??
|
||||
(await fastify.prisma.user.create({
|
||||
data: { ...defaultUser, email },
|
||||
data: createUserInput(email),
|
||||
select: { id: true }
|
||||
}))
|
||||
);
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { Prisma } from '@prisma/client';
|
||||
import { ObjectId } from 'mongodb';
|
||||
import _ from 'lodash';
|
||||
|
||||
import { defaultUser } from '../utils/default-user';
|
||||
import { createUserInput } from '../utils/create-user';
|
||||
import {
|
||||
defaultUserId,
|
||||
defaultUserEmail,
|
||||
@@ -18,8 +18,7 @@ import { JWT_SECRET } from '../utils/env';
|
||||
|
||||
// This is used to build a test user.
|
||||
const testUserData: Prisma.userCreateInput = {
|
||||
...defaultUser,
|
||||
email: defaultUserEmail,
|
||||
...createUserInput(defaultUserEmail),
|
||||
username: 'foobar',
|
||||
usernameDisplay: 'Foo Bar',
|
||||
progressTimestamps: [1520002973119, 1520440323273],
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import crypto from 'node:crypto';
|
||||
|
||||
import { type Prisma } from '@prisma/client';
|
||||
|
||||
/**
|
||||
* Creates the necessary data to create a new user.
|
||||
* @param email The email address of the new user.
|
||||
* @returns Default data for a new user.
|
||||
*/
|
||||
export function createUserInput(email: string): Prisma.userCreateInput {
|
||||
const username = 'fcc-' + crypto.randomUUID();
|
||||
const externalId = crypto.randomUUID();
|
||||
// This explicitly includes all array fields. This is not strictly necessary -
|
||||
// Prisma will return an empty array even if the property is missing, but it's
|
||||
// probably best to add them to the document, at least until we normalise the
|
||||
// data.
|
||||
return {
|
||||
about: '',
|
||||
acceptedPrivacyTerms: false,
|
||||
completedChallenges: [], // TODO(Post-MVP): Omit this from the document? (prisma will always return [])
|
||||
currentChallengeId: '',
|
||||
donationEmails: [], // TODO(Post-MVP): Omit this from the document? (prisma will always return [])
|
||||
email,
|
||||
emailVerified: true, // this should be true until a user changes their email address
|
||||
// TODO(Post-MVP): remove externalId?
|
||||
externalId,
|
||||
is2018DataVisCert: false,
|
||||
is2018FullStackCert: false,
|
||||
isApisMicroservicesCert: false,
|
||||
isBackEndCert: false,
|
||||
isBanned: false,
|
||||
isCheater: false,
|
||||
isDataAnalysisPyCertV7: false,
|
||||
isDataVisCert: false,
|
||||
isDonating: false,
|
||||
isFrontEndCert: false,
|
||||
isFrontEndLibsCert: false,
|
||||
isFullStackCert: false,
|
||||
isHonest: false,
|
||||
isInfosecCertV7: false,
|
||||
isInfosecQaCert: false,
|
||||
isJsAlgoDataStructCert: false,
|
||||
isMachineLearningPyCertV7: false,
|
||||
isQaCertV7: false,
|
||||
isRelationalDatabaseCertV8: false,
|
||||
isCollegeAlgebraPyCertV8: false,
|
||||
isRespWebDesignCert: false,
|
||||
isSciCompPyCertV7: false,
|
||||
keyboardShortcuts: false,
|
||||
location: '',
|
||||
name: '',
|
||||
unsubscribeId: '',
|
||||
partiallyCompletedChallenges: [], // TODO(Post-MVP): Omit this from the document? (prisma will always return [])
|
||||
picture: '',
|
||||
portfolio: [], // TODO(Post-MVP): Omit this from the document? (prisma will always return [])
|
||||
profileUI: {
|
||||
isLocked: false,
|
||||
showAbout: false,
|
||||
showCerts: false,
|
||||
showDonation: false,
|
||||
showHeatMap: false,
|
||||
showLocation: false,
|
||||
showName: false,
|
||||
showPoints: false,
|
||||
showPortfolio: false,
|
||||
showTimeLine: false
|
||||
},
|
||||
progressTimestamps: [], // TODO(Post-MVP): This may need normalising before we can omit it.
|
||||
savedChallenges: [], // TODO(Post-MVP): Omit this from the document? (prisma will always return [])
|
||||
sendQuincyEmail: false,
|
||||
theme: 'default',
|
||||
username,
|
||||
usernameDisplay: username,
|
||||
yearsTopContributor: [] // TODO: Omit this from the document? (prisma will always return [])
|
||||
};
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
// TODO: audit this object to find out which properties need to be updated.
|
||||
import { type Prisma } from '@prisma/client';
|
||||
|
||||
export const defaultUser: Omit<Prisma.userCreateInput, 'email'> = {
|
||||
about: '',
|
||||
acceptedPrivacyTerms: false,
|
||||
completedChallenges: [],
|
||||
currentChallengeId: '',
|
||||
emailVerified: true, // this should be true until a user changes their email address
|
||||
externalId: '',
|
||||
is2018DataVisCert: false,
|
||||
is2018FullStackCert: false,
|
||||
isApisMicroservicesCert: false,
|
||||
isBackEndCert: false,
|
||||
isBanned: false,
|
||||
isCheater: false,
|
||||
isDataAnalysisPyCertV7: false,
|
||||
isDataVisCert: false,
|
||||
isDonating: false,
|
||||
isFrontEndCert: false,
|
||||
isFrontEndLibsCert: false,
|
||||
isFullStackCert: false,
|
||||
isHonest: false,
|
||||
isInfosecCertV7: false,
|
||||
isInfosecQaCert: false,
|
||||
isJsAlgoDataStructCert: false,
|
||||
isMachineLearningPyCertV7: false,
|
||||
isQaCertV7: false,
|
||||
isRelationalDatabaseCertV8: false,
|
||||
isCollegeAlgebraPyCertV8: false,
|
||||
isRespWebDesignCert: false,
|
||||
isSciCompPyCertV7: false,
|
||||
keyboardShortcuts: false,
|
||||
location: '',
|
||||
name: '',
|
||||
unsubscribeId: '',
|
||||
picture: '',
|
||||
profileUI: {
|
||||
isLocked: false,
|
||||
showAbout: false,
|
||||
showCerts: false,
|
||||
showDonation: false,
|
||||
showHeatMap: false,
|
||||
showLocation: false,
|
||||
showName: false,
|
||||
showPoints: false,
|
||||
showPortfolio: false,
|
||||
showTimeLine: false
|
||||
},
|
||||
progressTimestamps: [],
|
||||
sendQuincyEmail: false,
|
||||
theme: 'default',
|
||||
// TODO: generate a UUID like in api-server
|
||||
username: ''
|
||||
};
|
||||
Reference in New Issue
Block a user