-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: adding JOI validiation to backend
Installed JOI validation package Added validation for the following endpoints: document - createDocument, deleteDocument, listDocuments note - createNote, listNotes permit - createPermit, deletePermit, listPermits, updatePermit, submission - getStatistics, getSubmission, editSubmission user - searchUser Validator files under src/validators Middleware under src/middeleware/validation.ts Modified frontend NoteCard, NoteModal, PermitModal to submit ISO dates for notes entries Modified frontend SubmissionForm onSubmit JSON to match valid format
- Loading branch information
Showing
23 changed files
with
399 additions
and
37 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
// @ts-expect-error api-problem lacks a defined interface; code still works fine | ||
import Problem from 'api-problem'; | ||
import type { NextFunction, Request, Response } from '../interfaces/IExpress'; | ||
// import type { NextFunction, Request, Response } from 'express'; | ||
|
||
/** | ||
* @function validator | ||
* Performs express request validation against a specified `schema` | ||
* @param {object} schema An object containing Joi validation schema definitions | ||
* @returns {function} Express middleware function | ||
* @throws The error encountered upon failure | ||
*/ | ||
export const validate = (schema: object) => { | ||
return (req: Request, _res: Response, next: NextFunction) => { | ||
const validationErrors = Object.entries(schema) | ||
.map(([prop, def]) => { | ||
const result = def.validate((req as any)[prop], { abortEarly: false })?.error; | ||
return result ? [prop, result?.details] : undefined; | ||
}) | ||
.filter((error) => !!error) | ||
.map((x) => x as any[]); | ||
|
||
if (Object.keys(validationErrors).length) { | ||
throw new Problem(422, { | ||
detail: validationErrors.flatMap((groups) => groups[1]?.map((error: any) => error?.message)).join('; '), | ||
instance: req.originalUrl, | ||
errors: Object.fromEntries(validationErrors) | ||
}); | ||
} else next(); | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,31 @@ | ||
import express from 'express'; | ||
import { documentController } from '../../controllers'; | ||
import { requireSomeAuth } from '../../middleware/requireSomeAuth'; | ||
import { documentValidator } from '../../validators'; | ||
|
||
import type { NextFunction, Request, Response } from '../../interfaces/IExpress'; | ||
|
||
const router = express.Router(); | ||
router.use(requireSomeAuth); | ||
|
||
router.put('/', (req: Request, res: Response, next: NextFunction): void => { | ||
router.put('/', documentValidator.createDocument, (req: Request, res: Response, next: NextFunction): void => { | ||
documentController.createDocument(req, res, next); | ||
}); | ||
|
||
router.delete('/:documentId', (req: Request, res: Response, next: NextFunction): void => { | ||
documentController.deleteDocument(req, res, next); | ||
}); | ||
router.delete( | ||
'/:documentId', | ||
documentValidator.deleteDocument, | ||
(req: Request, res: Response, next: NextFunction): void => { | ||
documentController.deleteDocument(req, res, next); | ||
} | ||
); | ||
|
||
router.get('/list/:activityId', (req: Request, res: Response, next: NextFunction): void => { | ||
documentController.listDocuments(req, res, next); | ||
}); | ||
router.get( | ||
'/list/:activityId', | ||
documentValidator.listDocuments, | ||
(req: Request, res: Response, next: NextFunction): void => { | ||
documentController.listDocuments(req, res, next); | ||
} | ||
); | ||
|
||
export default router; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import Joi from 'joi'; | ||
|
||
export const activityId = Joi.string().min(8).max(8).required(); | ||
|
||
export const uuidv4 = Joi.string().guid({ version: 'uuidv4' }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import Joi from 'joi'; | ||
|
||
import { activityId, uuidv4 } from './common'; | ||
import { validate } from '../middleware/validation'; | ||
|
||
const schema = { | ||
createDocument: { | ||
body: Joi.object({ | ||
activityId: activityId, | ||
documentId: uuidv4.required(), | ||
filename: Joi.string().max(255).required(), | ||
mimeType: Joi.string().max(255).required(), | ||
length: Joi.number().required() | ||
}) | ||
}, | ||
deleteDocument: { | ||
params: Joi.object({ | ||
documentId: Joi.string().max(255).required() | ||
}) | ||
}, | ||
listDocuments: { | ||
params: Joi.object({ | ||
activityId: activityId | ||
}) | ||
} | ||
}; | ||
|
||
export default { | ||
createDocument: validate(schema.createDocument), | ||
deleteDocument: validate(schema.deleteDocument), | ||
listDocuments: validate(schema.listDocuments) | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export { default as documentValidator } from './document'; | ||
export { default as noteValidator } from './note'; | ||
export { default as permitValidator } from './permit'; | ||
export { default as submissionValidator } from './submission'; | ||
export { default as userValidator } from './user'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import Joi from 'joi'; | ||
|
||
import { activityId } from './common'; | ||
import { validate } from '../middleware/validation'; | ||
|
||
const schema = { | ||
createNote: { | ||
body: Joi.object({ | ||
createdAt: Joi.date().required(), | ||
activityId: activityId, | ||
note: Joi.string(), | ||
noteType: Joi.string().max(255).required(), | ||
title: Joi.string().max(255) | ||
}) | ||
}, | ||
listNotes: { | ||
params: Joi.object({ | ||
activityId: activityId | ||
}) | ||
} | ||
}; | ||
|
||
export default { | ||
createNote: validate(schema.createNote), | ||
listNotes: validate(schema.listNotes) | ||
}; |
Oops, something went wrong.