Conversation
… email with hardcoded pandadoc links. sanitized output with escapeHTML
…on thrown by class validator in DTO
SamNie2027
left a comment
There was a problem hiding this comment.
Please resolve the failing tests
| * POST /api/applications endpoint fails due to validation errors. | ||
| * | ||
| * Applied at the controller-method level so it only intercepts | ||
| * BadRequestExceptions thrown during application creation. |
There was a problem hiding this comment.
It should intercept all error messages, not just BadRequestExceptions.
If the other Exceptions/ Errors aren't covered too, then a person will submit a Pandadoc and we will error out, causing their application not to be a part of our database, and the person who submitted it will never know that it failed.
| 'No email found in request body. Skipping error email.', | ||
| ); | ||
| } else { | ||
| const applicant = await this.usersService.findOne(recipientEmail); |
There was a problem hiding this comment.
Don't check for applicant existing at this point - because at this point the user won't even exist yet, this is at step 1 when the user submits the pandadoc before any data about them is written in the backend
There was a problem hiding this comment.
I am checking for this because I need to get the name of the applicant as per the email template. This name field does not exist in ApplicationDTO, but in Users which is tied to the application via its email? Should I fetch the name from somewhere else? or just Ignore the name field
|
|
||
| if (!applicant) { | ||
| this.logger.warn( | ||
| `No user found for email: ${recipientEmail}. Skipping error email.`, |
There was a problem hiding this comment.
To the above point ^ don't have this check
| ); | ||
| } else { | ||
| const applicantName = `${escapeHtml( | ||
| applicant.firstName, |
There was a problem hiding this comment.
Get the firstname and lastname from the application data from pandadoc instead, not the applicant as previously discussed
| import { UsersService } from '../users/users.service'; | ||
| import { FIELD_LABELS } from './types'; | ||
|
|
||
| function escapeHtml(text: string): string { |
There was a problem hiding this comment.
Documentation here would be nice
| * "appStatus must be one of..." → "Application Status must be one of..." | ||
| * "each value in interest must be one of..." → "Each value in Areas of Interest must be one of..." | ||
| */ | ||
| private humanizeErrorMessage(message: string): string { |
There was a problem hiding this comment.
Remember to include info about the parameter when doing documentation
| applicantName: string, | ||
| requestBody: Record<string, unknown>, | ||
| errorMessages: string[], | ||
| ): string { |
There was a problem hiding this comment.
Remember to include info about parameter format when doing documentation and also include what it returns
| * Only includes fields that have a friendly label defined in FIELD_LABELS. | ||
| * Skips null/undefined values. | ||
| */ | ||
| private formatSubmittedFields(body: Record<string, unknown>): string { |
There was a problem hiding this comment.
Again remember to put info about the parameters in the documentation
| } | ||
|
|
||
| /** User-friendly labels for request body fields displayed in the error email. */ | ||
| export const FIELD_LABELS: Record<string, string> = { |
There was a problem hiding this comment.
My issue with this is that this is not the pandadoc fields - these are out database fields, which are in a different format than what the applicant submits.
Instead of fixing this, if alternatively you can find evidence that pandadoc can send a copy of their submission back to the user every time they submit, then that will negate the need for this
There was a problem hiding this comment.
Yea i totally agree i think having a mapping is a bit impractical, ill go look around for functionality on how to get pandadoc to send a copy of the submission in human-readable format over
There was a problem hiding this comment.
Can use this instead to fetch the fields:
https://developers.pandadoc.com/reference/document-details
…ts to the name "Applicant"
…error, then sending submission-error-email
…error when processing email past the DTO validation stage + moved filters to filter folder
…ervice usage is moved to the filters
… before app validation (NestJS reverses the order) no longer need to check for badrequestexception in the second filter
…into 212-error-email
…ints receive DTO information

ℹ️ Issue
Closes #212
📝 Description
Write a short summary of what you added. Why is it important? Any member of C4C should be able to read this and understand your contribution -- not just your team members.
Because the DTO already includes input validation, I added a filter on the controller that handles BadRequestExceptions and sends the user an email with the errors in human-readable format.
Example DTO with input validation:

Briefly list the changes made to the code:
✔️ Verification
What steps did you take to verify your changes work? These should be clear enough for someone to be able to clone the branch and follow the steps themselves.
Example email:

🏕️ (Optional) Future Work / Notes
Got rid of input validation in service, as it is redundant and requests hitting the endpoint already get validated and error-handled by the controller. The filter handles errors thrown by controller-level validation errors, and sends emails from there