Skip to content

Commit 2229ad1

Browse files
author
Joshua Zhou
committed
more validation
1 parent b82b20c commit 2229ad1

File tree

5 files changed

+119
-12
lines changed

5 files changed

+119
-12
lines changed

constants/checkin-options.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Team checkin form constants for Mchacks 13
2+
"use strict";
3+
4+
const PRIZE_CATEGORIES = [
5+
"Best Beginner Hack",
6+
"Best Design",
7+
"Chaotic Evil",
8+
"Best Use of AI or AI Agents"
9+
];
10+
11+
const SPONSOR_CHALLENGES = [
12+
"HoloRay",
13+
"Athena AI",
14+
"Gumloop",
15+
"National Bank",
16+
"Tail'ed",
17+
"BassiliChat AI",
18+
"Dobson Center",
19+
"Desjardins",
20+
"NOVA",
21+
"CSUS"
22+
];
23+
24+
const MLH_CHALLENGES = [
25+
"Best Use of ElevenLabs",
26+
"Best Use of Gemini API",
27+
"Best Use of MongoDB Atlas",
28+
"Best Use of DigitalOcean",
29+
"Best Use of Solana",
30+
"Best Use of Auth0"
31+
];
32+
33+
module.exports = {
34+
PRIZE_CATEGORIES,
35+
SPONSOR_CHALLENGES,
36+
MLH_CHALLENGES
37+
};

controllers/checkin.controller.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ async function submitCheckin(req, res) {
7474
teamMember4: teamMemberEmails[3] || '',
7575
prizeCategories: req.body.formData.prizeCategories,
7676
sponsorChallenges: req.body.formData.sponsorChallenges,
77+
mlhChallenges: req.body.formData.mlhChallenges,
7778
// workshopsAttended: req.body.formData.workshopsAttended,
7879
discordTag: req.body.formData.discordTag,
7980
devpostLink: req.body.formData.devpostLink,
Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,58 @@
11
"use strict";
22

33
const { body } = require('express-validator');
4+
const {
5+
PRIZE_CATEGORIES,
6+
SPONSOR_CHALLENGES,
7+
MLH_CHALLENGES
8+
} = require('../../constants/checkin-options');
49

510
/**
611
* Validator for check-in form submission
712
*/
813
const checkinValidator = [
9-
body('formData.prizeCategories').isArray().withMessage('Prize categories must be an array'),
10-
body('formData.sponsorChallenges').isArray().withMessage('Sponsor challenges must be an array'),
14+
body('formData.prizeCategories')
15+
.isArray()
16+
.withMessage('Prize categories must be an array')
17+
.custom((values) =>
18+
Array.isArray(values) &&
19+
values.every((value) => typeof value === 'string' && PRIZE_CATEGORIES.includes(value))
20+
)
21+
.withMessage('Prize categories contain invalid selections'),
22+
body('formData.sponsorChallenges')
23+
.isArray()
24+
.withMessage('Sponsor challenges must be an array')
25+
.custom((values) =>
26+
Array.isArray(values) &&
27+
values.every((value) => typeof value === 'string' && SPONSOR_CHALLENGES.includes(value))
28+
)
29+
.withMessage('Sponsor challenges contain invalid selections'),
30+
body('formData.mlhChallenges')
31+
.isArray()
32+
.withMessage('MLH challenges must be an array')
33+
.custom((values) =>
34+
Array.isArray(values) &&
35+
values.every((value) => typeof value === 'string' && MLH_CHALLENGES.includes(value))
36+
)
37+
.withMessage('MLH challenges contain invalid selections'),
1138
// body('formData.workshopsAttended').isArray().withMessage('Workshops attended must be an array'),
1239
body('formData.discordTag').notEmpty().withMessage('Discord tag is required'),
13-
body('formData.devpostLink').notEmpty().withMessage('Devpost link is required')
40+
body('formData.devpostLink')
41+
.notEmpty()
42+
.withMessage('Devpost link is required')
43+
.bail()
44+
.isURL({ require_protocol: true, protocols: ['http', 'https'] })
45+
.withMessage('Devpost link must be a valid URL')
46+
.bail()
47+
.custom((value) => {
48+
try {
49+
const url = new URL(value);
50+
return url.hostname === 'devpost.com' || url.hostname.endsWith('.devpost.com');
51+
} catch (error) {
52+
return false;
53+
}
54+
})
55+
.withMessage('Devpost link must be a devpost.com URL')
1456
];
1557

1658
module.exports = checkinValidator;

routes/api/checkin.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const Middleware = {
2626
* @apiParam {Object} formData The check-in form data
2727
* @apiParam {String[]} formData.prizeCategories Array of prize categories
2828
* @apiParam {String[]} formData.sponsorChallenges Array of sponsor challenges
29+
* @apiParam {String[]} formData.mlhChallenges Array of MLH challenges
2930
* @apiParam {String[]} formData.workshopsAttended Array of workshops attended
3031
*
3132
* @apiSuccess {String} message Success message

services/sheets.service.js

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,31 @@ class SheetsService {
2727
});
2828
}
2929

30+
sanitizeForSheet(value) {
31+
if (typeof value !== 'string') {
32+
return value;
33+
}
34+
if (
35+
value.startsWith('=') ||
36+
value.startsWith('+') ||
37+
value.startsWith('-') ||
38+
value.startsWith('@')
39+
) {
40+
return `'${value}`;
41+
}
42+
return value;
43+
}
44+
45+
sanitizeArrayForSheet(values) {
46+
if (!Array.isArray(values)) {
47+
return '';
48+
}
49+
return values
50+
.filter((value) => typeof value === 'string')
51+
.map((value) => this.sanitizeForSheet(value))
52+
.join(', ');
53+
}
54+
3055
/**
3156
* Append check-in data to the spreadsheet
3257
* @param {Object} formData The check-in form data
@@ -49,16 +74,17 @@ class SheetsService {
4974
// Format the data for the spreadsheet
5075
const values = [[
5176
new Date().toISOString(),
52-
formData.teamMember1 || '',
53-
formData.teamMember2 || '',
54-
formData.teamMember3 || '',
55-
formData.teamMember4 || '',
56-
Array.isArray(formData.prizeCategories) ? formData.prizeCategories.join(', ') : '',
57-
Array.isArray(formData.sponsorChallenges) ? formData.sponsorChallenges.join(', ') : '',
77+
this.sanitizeForSheet(formData.teamMember1 || ''),
78+
this.sanitizeForSheet(formData.teamMember2 || ''),
79+
this.sanitizeForSheet(formData.teamMember3 || ''),
80+
this.sanitizeForSheet(formData.teamMember4 || ''),
81+
this.sanitizeArrayForSheet(formData.prizeCategories),
82+
this.sanitizeArrayForSheet(formData.sponsorChallenges),
83+
this.sanitizeArrayForSheet(formData.mlhChallenges),
5884
// Array.isArray(formData.workshopsAttended) ? formData.workshopsAttended.join(', ') : '',
59-
formData.discordTag || '',
60-
formData.devpostLink || '',
61-
formData.teamId || '' // Add teamId at the 'K' column
85+
this.sanitizeForSheet(formData.discordTag || ''),
86+
this.sanitizeForSheet(formData.devpostLink || ''),
87+
this.sanitizeForSheet(formData.teamId || '') // Add teamId at the 'K' column
6288
]];
6389

6490
Logger.info('Formatted data for spreadsheet:', values);

0 commit comments

Comments
 (0)