mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-04-10 13:00:59 -04:00
feat(client/api): add C# survey (#51682)
This commit is contained in:
@@ -7,6 +7,7 @@ import fetch from 'node-fetch';
|
||||
import {
|
||||
fixCompletedChallengeItem,
|
||||
fixCompletedExamItem,
|
||||
fixCompletedSurveyItem,
|
||||
fixPartiallyCompletedChallengeItem,
|
||||
fixSavedChallengeItem
|
||||
} from '../../common/utils';
|
||||
@@ -24,6 +25,7 @@ import {
|
||||
encodeUserToken
|
||||
} from '../middlewares/user-token';
|
||||
import { createDeleteMsUsername } from '../middlewares/ms-username';
|
||||
import { validateSurvey, createDeleteUserSurveys } from '../middlewares/survey';
|
||||
import { deprecatedEndpoint } from '../utils/disabled-endpoints';
|
||||
|
||||
const log = debugFactory('fcc:boot:user');
|
||||
@@ -39,6 +41,8 @@ function bootUser(app) {
|
||||
const deleteUserToken = createDeleteUserToken(app);
|
||||
const postMsUsername = createPostMsUsername(app);
|
||||
const deleteMsUsername = createDeleteMsUsername(app);
|
||||
const postSubmitSurvey = createPostSubmitSurvey(app);
|
||||
const deleteUserSurveys = createDeleteUserSurveys(app);
|
||||
|
||||
api.get('/account', sendNonUserToHome, deprecatedEndpoint);
|
||||
api.get('/account/unlink/:social', sendNonUserToHome, getUnlinkSocial);
|
||||
@@ -48,6 +52,7 @@ function bootUser(app) {
|
||||
ifNoUser401,
|
||||
deleteUserToken,
|
||||
deleteMsUsername,
|
||||
deleteUserSurveys,
|
||||
postDeleteAccount
|
||||
);
|
||||
api.post(
|
||||
@@ -55,6 +60,7 @@ function bootUser(app) {
|
||||
ifNoUser401,
|
||||
deleteUserToken,
|
||||
deleteMsUsername,
|
||||
deleteUserSurveys,
|
||||
postResetProgress
|
||||
);
|
||||
api.post(
|
||||
@@ -80,6 +86,13 @@ function bootUser(app) {
|
||||
deleteMsUsernameResponse
|
||||
);
|
||||
|
||||
api.post(
|
||||
'/user/submit-survey',
|
||||
ifNoUser401,
|
||||
validateSurvey,
|
||||
postSubmitSurvey
|
||||
);
|
||||
|
||||
app.use(api);
|
||||
}
|
||||
|
||||
@@ -206,8 +219,50 @@ function deleteMsUsernameResponse(req, res) {
|
||||
return res.send({ msUsername: null });
|
||||
}
|
||||
|
||||
function createPostSubmitSurvey(app) {
|
||||
const { Survey } = app.models;
|
||||
|
||||
return async function postSubmitSurvey(req, res) {
|
||||
const { user, body } = req;
|
||||
const { surveyResults } = body;
|
||||
const { completedSurveys = [] } = user;
|
||||
const { title } = surveyResults;
|
||||
|
||||
const surveyAlreadyTaken = completedSurveys.some(s => s.title === title);
|
||||
if (surveyAlreadyTaken) {
|
||||
return res.status(400).json({
|
||||
type: 'error',
|
||||
message: 'flash.survey.err-2'
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const newSurvey = {
|
||||
...surveyResults,
|
||||
userId: user.id
|
||||
};
|
||||
|
||||
const createdSurvey = await Survey.create(newSurvey);
|
||||
if (!createdSurvey) {
|
||||
throw new Error('Error creating survey');
|
||||
}
|
||||
|
||||
return res.json({
|
||||
type: 'success',
|
||||
message: 'flash.survey.success'
|
||||
});
|
||||
} catch (e) {
|
||||
log(e);
|
||||
return res.status(500).json({
|
||||
type: 'error',
|
||||
message: 'flash.survey.err-3'
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function createReadSessionUser(app) {
|
||||
const { MsUsername, UserToken } = app.models;
|
||||
const { MsUsername, Survey, UserToken } = app.models;
|
||||
|
||||
return async function getSessionUser(req, res, next) {
|
||||
const queryUser = req.user;
|
||||
@@ -240,6 +295,18 @@ function createReadSessionUser(app) {
|
||||
return next(e);
|
||||
}
|
||||
|
||||
let completedSurveys;
|
||||
try {
|
||||
const userId = queryUser?.id;
|
||||
completedSurveys = userId
|
||||
? await Survey.find({
|
||||
where: { userId }
|
||||
})
|
||||
: [];
|
||||
} catch (e) {
|
||||
return next(e);
|
||||
}
|
||||
|
||||
if (!queryUser || !queryUser.toJSON().username) {
|
||||
// TODO: This should return an error status
|
||||
return res.json({ user: {}, result: '' });
|
||||
@@ -282,7 +349,8 @@ function createReadSessionUser(app) {
|
||||
...normaliseUserFields(user),
|
||||
joinDate: user.id.getTimestamp(),
|
||||
userToken: encodedUserToken,
|
||||
msUsername
|
||||
msUsername,
|
||||
completedSurveys: completedSurveys.map(fixCompletedSurveyItem)
|
||||
}
|
||||
},
|
||||
result: user.username
|
||||
|
||||
41
api-server/src/server/middlewares/survey.js
Normal file
41
api-server/src/server/middlewares/survey.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import debugFactory from 'debug';
|
||||
const log = debugFactory('fcc:boot:user');
|
||||
|
||||
const allowedTitles = ['Foundational C# with Microsoft Survey'];
|
||||
|
||||
export function validateSurvey(req, res, next) {
|
||||
const {
|
||||
surveyResults: { title = '', responses = [] }
|
||||
} = req.body;
|
||||
|
||||
if (
|
||||
!allowedTitles.includes(title) ||
|
||||
!Array.isArray(responses) ||
|
||||
!responses.every(
|
||||
r => typeof r.question === 'string' && typeof r.response === 'string'
|
||||
)
|
||||
) {
|
||||
return res.status(400).json({
|
||||
type: 'error',
|
||||
message: 'flash.survey.err-1'
|
||||
});
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
export function createDeleteUserSurveys(app) {
|
||||
const { Survey } = app.models;
|
||||
|
||||
return async function deleteUserSurveys(req, res, next) {
|
||||
try {
|
||||
await Survey.destroyAll({ userId: req.user.id });
|
||||
req.userSurveysDeleted = true;
|
||||
} catch (e) {
|
||||
req.userSurveysDeleted = false;
|
||||
log(`An error occurred deleting Surveys for user with id ${req.user.id}`);
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
}
|
||||
@@ -47,6 +47,10 @@
|
||||
"dataSource": "db",
|
||||
"public": false
|
||||
},
|
||||
"Survey": {
|
||||
"dataSource": "db",
|
||||
"public": false
|
||||
},
|
||||
"RoleMapping": {
|
||||
"dataSource": "db",
|
||||
"public": false
|
||||
|
||||
41
api-server/src/server/models/survey.json
Normal file
41
api-server/src/server/models/survey.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "Survey",
|
||||
"description": "Survey responses from campers",
|
||||
"base": "PersistedModel",
|
||||
"idInjection": true,
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"type": [
|
||||
{
|
||||
"question": "string",
|
||||
"response": "string"
|
||||
}
|
||||
],
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"validations": [],
|
||||
"relations": {
|
||||
"user": {
|
||||
"type": "belongsTo",
|
||||
"model": "user",
|
||||
"foreignKey": "userId"
|
||||
}
|
||||
},
|
||||
"acls": [
|
||||
{
|
||||
"accessType": "*",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "DENY"
|
||||
}
|
||||
],
|
||||
"methods": {}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ export const publicUserProps = [
|
||||
'calendar',
|
||||
'completedChallenges',
|
||||
'completedExams',
|
||||
'completedSurveys',
|
||||
'githubProfile',
|
||||
'isApisMicroservicesCert',
|
||||
'isBackEndCert',
|
||||
|
||||
Reference in New Issue
Block a user