feat(api): add PUT /certificate/verify (#51507)

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
Shaun Hamilton
2024-02-28 18:01:35 +02:00
committed by GitHub
parent 64bf9defcd
commit bbc1ffa489
10 changed files with 1102 additions and 19 deletions

View File

@@ -34,6 +34,7 @@ export function createUserInput(email: string): Prisma.userCreateInput {
isDataAnalysisPyCertV7: false,
isDataVisCert: false,
isDonating: false,
isFoundationalCSharpCertV8: false,
isFrontEndCert: false,
isFrontEndLibsCert: false,
isFullStackCert: false,

View File

@@ -39,6 +39,7 @@ assert.ok(process.env.FCC_ENABLE_SWAGGER_UI);
assert.ok(process.env.FCC_ENABLE_DEV_LOGIN_MODE);
assert.ok(process.env.JWT_SECRET);
assert.ok(process.env.STRIPE_SECRET_KEY);
assert.ok(process.env.SHOW_UPCOMING_CHANGES);
if (process.env.FREECODECAMP_NODE_ENV !== 'development') {
assert.ok(process.env.SES_ID);
@@ -109,4 +110,6 @@ export const SES_ID = process.env.SES_ID;
export const SES_SECRET = process.env.SES_SECRET;
export const SES_REGION = process.env.SES_REGION;
export const EMAIL_PROVIDER = process.env.EMAIL_PROVIDER;
export const SHOW_UPCOMING_CHANGES =
process.env.SHOW_UPCOMING_CHANGES === 'true';
export const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY;

View File

@@ -3,10 +3,15 @@
// redirectToCurrentChallenge and, instead, only report the current challenge id
// via the user object, then we should *not* store this so it can be garbage
// collected.
import curriculum from '../../../shared/config/curriculum.json';
import { SuperBlocks } from '../../../shared/config/superblocks';
import { readFileSync } from 'fs';
import { join } from 'path';
type Curriculum = { [keyValue in SuperBlocks]?: CurriculumProps };
const CURRICULUM_PATH = '../shared/config/curriculum.json';
// Curriculum is read using fs, because it is too large for VSCode's LSP to handle type inference which causes anoying behaviour.
const curriculum = JSON.parse(
readFileSync(join(process.cwd(), CURRICULUM_PATH), 'utf-8')
) as Curriculum;
interface Block {
challenges: {
@@ -18,25 +23,30 @@ interface Block {
}[];
}
interface CurriculumProps {
type SuperBlock = {
blocks: Record<string, Block>;
}
};
type Curriculum = Record<string, SuperBlock>;
/**
* Get all the challenges from the curriculum.
* @returns An array of challenges.
* Get all challenges including all certifications as "challenges" (ids and tests).
* @returns The whole curricula reduced to an array.
*/
export function getChallenges() {
const superBlockKeys = Object.values(SuperBlocks);
const typedCurriculum: Curriculum = curriculum as Curriculum;
export function getChallenges(): Block['challenges'] {
const curricula = Object.values(curriculum);
return superBlockKeys
.map(key => typedCurriculum[key]?.blocks)
.reduce((accumulator: Block['challenges'], superBlock) => {
const blockKeys = Object.keys(superBlock ?? {});
const challengesForBlock = blockKeys.map(
key => superBlock?.[key]?.challenges ?? []
);
return [...accumulator, ...challengesForBlock.flat()];
return curricula
.map(v => v.blocks)
.reduce((acc: Block['challenges'], superBlock) => {
const blockKeys = Object.keys(superBlock);
const challengesForBlock = blockKeys.map(k => {
const block = superBlock[k];
if (!block) {
return [];
}
return block.challenges;
});
return [...acc, ...challengesForBlock.flat()];
}, []);
}