Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,12 @@ app.use(express.json())
// Routes
app.use('/contribute/add-new-component', addComponentRoutes)

app.get("/contribute/debug-sentry", function mainHandler(req, res) {
throw new Error("My first Sentry error!");
});

// Fallback route to homepage
// Fallback route to 404
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'))
// res.sendFile(path.join(__dirname, 'public', 'index.html'))
res.status(404).render('error', {
message: 'Page not found.'
})
})

// The error handler must be registered before any other error middleware and after all controllers
Expand Down
10 changes: 7 additions & 3 deletions config.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,11 @@ const config = {
'component-code-details': {
fields: {
componentCodeLanguage: {
label: 'What language is the code?',
hint: "Enter a language such as HTML, CSS, SASS or Javascript. It's easier if the code is in one language."
label: 'Select the code language',
hint: "If you have code in 2 or more languages you can add another code example."
},
componentCodeLanguageOther: {
label: "Enter the code language"
},
componentCodeUsage: {
label: 'How do you use the code? (optional)',
Expand Down Expand Up @@ -215,7 +218,8 @@ const config = {
// prototypeUrlAdditionalInformation: 'Additional information',
// componentCode: 'Code',
// componentCodeUsage: 'Code usage',
// componentCodeLanguage: 'Code language ssdllklkj:w',
// componentCodeLanguage: 'Code language',
// componentCodeLanguageOther: 'Other code language',
// figmaLink: 'Prototype link',
// figmaLinkAdditionalInformation: 'Additional information',
// shareYourDetails: 'Share your details on the component page',
Expand Down
68 changes: 35 additions & 33 deletions helpers/check-your-answers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ const {

const { combineDateFields } = require('./date-fields')
const {
toCamelCaseWithRows,
humanReadableLabel: humanReadableLabelText,
replaceAcronyms,
truncateText,
Expand All @@ -23,18 +22,22 @@ const shareYourDetailsKeys = Object.keys(shareYourDetails)
/**
* Converts a text label to a human-readable format using a predefined mapping.
*
* @param {string} text - The text label to convert.
* @param {string} field - The camelCase field to get a label for.
* @param {string} form - The form/page that contains the field
* @returns {string} - The human-readable label.
*/
const humanReadableLabel = (field, form = '') => {
// If there's an override, use that
if (Object.keys(labelOverrides).includes(field)) {
return labelOverrides[field]
}
// Otherwise use the label from the form pages config
if (form) {
if (formPages[form]?.fields[field]?.label) {
return formPages[form]?.fields[field]?.label
}
}
// Else just convert the camelCase to human
return humanReadableLabelText(field)
}

Expand All @@ -60,7 +63,7 @@ const answersFromSession = (data, session, canRemove) => {
answers.push(...extractFieldData(formName, session, config))
}
} else {
answers.push(...extractFieldData(form, session, defaultConfig))
answers.push(...extractFieldData(form, session, defaultConfig))
}
})
console.log(answers)
Expand Down Expand Up @@ -103,8 +106,7 @@ const shareYourDetailsValueReplacement = (value) => {
*
* @param {string} field - The field to extract data for.
* @param {object} session - The session data.
* @param {Array} [canRemove] - The fields that can be removed.
* @param {Array} [ignoreFields] - The fields to ignore.
* @param {object} options - The options for extraction
* @returns {Array} - The extracted and formatted field data.
*/
// TODO: We don't need the whole session here! only the form we;re extracting
Expand All @@ -117,51 +119,51 @@ const extractFieldData = (field, session, options = {}) => {
includeFields: []
}
const opts = Object.assign({}, defaults, options)
console.log(opts)
console.log(opts)
const fieldName = field
const fieldPath = `/${field}`
console.log(`extracting field data for: ${fieldName}`)

let parsedSession = {}

if(opts.includeFields.length > 0) {
if (opts.includeFields.length > 0) {
console.log('only including specified fields')
for(const [key, value] of Object.entries(session)) {
for (const [key, value] of Object.entries(session)) {
if (typeof value === 'object' && !Array.isArray(value)) {

Object.keys(value).forEach(function(field){
console.log(field)
console.log(opts.includeFields)
if(opts.includeFields.includes(field) ) {
console.log('field should be included')
parsedSession[key] = {}
parsedSession[key][field] = value[field]
}
});

Object.keys(value).forEach(function (field) {
console.log(field)
console.log(opts.includeFields)
if (opts.includeFields.includes(field)) {
console.log('field should be included')
parsedSession[key] = {}
parsedSession[key][field] = value[field]
}
})
}
}
} else {
console.log('using whole session')
parsedSession = Object.assign({}, session)
}


// Remove excluded fields from session data
if(opts.excludeFields.length > 0) {
if (opts.excludeFields.length > 0) {
console.log('excluding fields')
parsedSession = Object.entries(parsedSession).reduce((acc, [key, value]) => {
if (typeof value === 'object' && !Array.isArray(value)) {
opts.excludeFields.forEach((excludeField) => {
if (value && typeof value === 'object' && excludeField in value) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete value[excludeField]
}
})
}
acc[key] = value
return acc
}, {})
parsedSession = Object.entries(parsedSession).reduce(
(acc, [key, value]) => {
if (typeof value === 'object' && !Array.isArray(value)) {
opts.excludeFields.forEach((excludeField) => {
if (value && typeof value === 'object' && excludeField in value) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete value[excludeField]
}
})
}
acc[key] = value
return acc
},
{}
)
}

console.log(parsedSession)
Expand Down
3 changes: 2 additions & 1 deletion helpers/mockSessionData/sessionData.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ module.exports = {
componentCodeAvailable: 'yes'
},
'/component-code-details': {
componentCodeLanguage: 'HTML',
componentCodeLanguage: 'Other',
componentCodeLanguageOther: 'Nunjucks',
componentCodeUsage:
'In lacus ipsum, molestie nec sapien vitae, tincidunt tristique nisi. Integer a lacus quis nisl mollis fringilla. Nullam blandit imperdiet mauris, ac feugiat ante. Vestibulum nec semper nulla, ut ultricies massa. Curabitur lacinia tortor augue, sed varius leo viverra non. Fusce vitae libero ac orci elementum vestibulum eu et libero. In rhoncus laoreet nisi, sit amet rutrum tellus. Ut ut dui in metus sodales molestie eu ut purus.\r\n\r\n',
componentCode: '<p>test</p>'
Expand Down
38 changes: 31 additions & 7 deletions middleware/component-session.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@ const getHashedUrl = (url) => {
return crypto.createHash('sha256').update(url).digest('hex')
}

const getTemplate = (req) => {
let template = `${req.params.page || req.url.replace('/', '')}`
if (!Object.keys(COMPONENT_FORM_PAGES).includes(template)) {
template = 'error'
}
return template
}

const getPageData = (req) => {
let pageData = `${req.params.page || req.url.replace('/', '')}`
if (!Object.keys(COMPONENT_FORM_PAGES).includes(pageData)) {
pageData = {}
}
return pageData
}

const transformErrorsToErrorList = (errors) => {
return errors.map((error) => ({
text: error.message,
Expand Down Expand Up @@ -53,9 +69,8 @@ const errorTemplateVariables = (
errorList,
formErrorStyles = null
) => {
const page = req.params.page || req.url.replace('/', '')
return {
page: COMPONENT_FORM_PAGES[page],
page: getPageData(req),
submitUrl: req.originalUrl,
formData: req.body,
file: req?.file,
Expand All @@ -78,12 +93,10 @@ const validateFormDataFileUpload = (err, req, res, next) => {
formErrors[err.field] = { text: errorMessage }
const errors = [{ message: errorMessage, path: [err.field] }]
const errorList = transformErrorsToErrorList(errors)
const template = getTemplate(req)
res
.status(400)
.render(
`${req.params.page || req.url.replace('/', '')}`,
errorTemplateVariables(req, formErrors, errorList)
)
.render(template, errorTemplateVariables(req, formErrors, errorList))
} else {
next()
}
Expand Down Expand Up @@ -130,10 +143,11 @@ const validateFormData = (req, res, next) => {
})

const errorList = transformErrorsToErrorList(errorListDetails)
const template = getTemplate(req)
res
.status(400)
.render(
`${req.params.page || req.url.replace('/', '')}`,
template,
errorTemplateVariables(req, formErrors, errorList, formErrorStyles)
)
} else {
Expand All @@ -159,6 +173,16 @@ const saveSession = (req, res, next) => {
}
}

// prevent prototype pollution
if (
req.url === '__proto__' ||
req.url === 'constructor' ||
req.url === 'prototype'
) {
res.end(403)
return
}

req.session[req.url] = { ...req.session[req.url], ...body }
delete req.session[req.url].addAnother

Expand Down
6 changes: 5 additions & 1 deletion middleware/generate-documentation.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ ${figma?.figmaLinkAdditionalInformation || ''}

### ${componentCodeDetails?.componentCodeLanguage || ''}

${componentCodeDetails?.componentCodeUsage || ''}
### ${componentCodeDetails?.componentCodeLanguageOther || ''}

<div class="app-example app-example-borders">

Expand All @@ -150,6 +150,10 @@ ${componentCodeDetails?.componentCode || ''}

</div>
`

${componentCodeDetails?.componentCodeUsage || ''}


n++
}
return content.length ? content : noCode
Expand Down
Loading
Loading