Skip to content

Commit

Permalink
[Tech Debt] Add request param validation
Browse files Browse the repository at this point in the history
  • Loading branch information
levinmr committed Nov 8, 2024
1 parent 0436acb commit 108c048
Show file tree
Hide file tree
Showing 4 changed files with 619 additions and 189 deletions.
40 changes: 39 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
"knex": "^3.0.1",
"lodash": ">= 4.17.21",
"pg": "^8.11.3",
"winston": "^3.11.0"
"winston": "^3.11.0",
"yup": "^1.4.0"
},
"optionalDependencies": {
"newrelic": "^11.3.0"
Expand Down
51 changes: 48 additions & 3 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const db = require("./db");
const logger = require("./logger");
const router = express.Router();
const routesVersioning = require("express-routes-versioning")();
const yup = require("yup");

const app = express();

Expand All @@ -15,6 +16,10 @@ app.use(apiDataGovFilter);
app.use(router);
app.use(logger.errorLoggingMiddleware());

/**

Check warning on line 19 in src/app.js

View workflow job for this annotation

GitHub Actions / lint

Missing JSDoc @returns declaration
* Converts date object to an ISO date string without time and zone.
* @param dataPoint

Check warning on line 21 in src/app.js

View workflow job for this annotation

GitHub Actions / lint

Missing JSDoc @param "dataPoint" description

Check warning on line 21 in src/app.js

View workflow job for this annotation

GitHub Actions / lint

Missing JSDoc @param "dataPoint" type
*/
const formatDateForDataPoint = (dataPoint) => {
if (dataPoint.date) {
return dataPoint.date.toISOString().slice(0, 10);
Expand All @@ -29,6 +34,17 @@ const acceptableDomainReports = [
"second-level-domain",
];

/**
* Currently the only regex match in request validation is on date string
* formatting. Hard code that the yup.string().matches() validation returns a
* helpful error message when dates are not formatted correctly.
*/
yup.setLocale({
string: {
matches: "must be a date in format 'YYYY-MM-DD'",
},
});

const checkDomainFilter = (req, res) => {
if (
acceptableDomainReports.includes(req.params.reportName) &&
Expand All @@ -45,8 +61,18 @@ const checkDomainFilter = (req, res) => {
};

const fetchData = (req, res) => {
try {
validateRequest(req);
} catch (err) {
res.status(400);
return res.json({
message: `Invalid request params: ${err}`,
status: 400,
});
}
const params = Object.assign(req.query, req.params);
db.query(params)
return db
.query(params)
.then((result) => {
const response = result.map((dataPoint) =>
Object.assign(
Expand All @@ -68,14 +94,33 @@ const fetchData = (req, res) => {
})
.catch((err) => {
console.error("Unexpected Error:", err);
res.status(400);
res.status(500);
return res.json({
message: "An error occurred. Please check the application logs.",
status: 400,
status: 500,
});
});
};

const validateRequest = (req) => {
const isoDateRegex = /^\d{4}-([0][1-9]|1[0-2])-([0][1-9]|[1-2]\d|3[01])$/;
const requestSchema = yup.object({
query: yup.object({
before: yup.string().matches(isoDateRegex),
after: yup.string().matches(isoDateRegex),
limit: yup.number().positive().integer().max(10000),
page: yup.number().positive().integer(),
}),
params: yup.object({
domain: yup.string(),
reportAgency: yup.string(),
reportName: yup.string(),
version: yup.string(),
}),
});
return requestSchema.validateSync(req);
};

app.get("/", (req, res) => {
res.json({
current_time: new Date(),
Expand Down
Loading

0 comments on commit 108c048

Please sign in to comment.