224 confirmation email when companies register#306
224 confirmation email when companies register#306FranciscoCardoso913 wants to merge 31 commits into
Conversation
|
Your Render PR Server URL is https://nijobs-be-pr-306.onrender.com. Follow its progress at https://dashboard.render.com/web/srv-cfk2gnhgp3jgtsvl5cu0. |
New workflowDiscussed solution
|
896610a to
441c78e
Compare
441c78e to
709babb
Compare
|
@FranciscoCardoso913 @dsantosferreira Updates on this? |
96a71fb to
dabb53b
Compare
| import { SECOND_IN_MS } from "../../models/constants/TimeConstants.js"; | ||
|
|
||
| export const exceededCreationTimeLimit = async (req, res, next) => { | ||
| const application = await CompanyApplication.findOne({ email: req.body.email, isVerified: false }); |
Check failure
Code scanning / CodeQL
Database query built from user-controlled sources
…ress Co-authored-by: Francisco Cardoso <FranciscoCardoso913@users.noreply.github.com>
Naapperas
left a comment
There was a problem hiding this comment.
Regarding the check annotations, GH does not have the ability to do an E2E security audit, from the looks of it. Most of the times the security issues that it signals are already being mitigated my validators/middleware. We should still see if these are valid just in case something slips through
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #306 +/- ##
===========================================
+ Coverage 90.34% 90.55% +0.21%
===========================================
Files 54 55 +1
Lines 1470 1546 +76
Branches 246 257 +11
===========================================
+ Hits 1328 1400 +72
- Misses 137 141 +4
Partials 5 5 ☔ View full report in Codecov by Sentry. |
5e73233 to
0be0cf9
Compare
33d750f to
5d65bf9
Compare
Co-authored-by: Francisco Cardoso <FranciscoCardoso913@users.noreply.github.com>
Co-authored-by: Francisco Cardoso <FranciscoCardoso913@users.noreply.github.com>
…lications Co-authored-by: Daniel Ferreira <dsantosferreira@users.noreply.github.com>
Co-authored-by: Daniel Ferreira <dsantosferreira@users.noreply.github.com>
…ication Co-authored-by: Daniel Ferreira <dsantosferreira@users.noreply.github.com>
Co-authored-by: Francisco Cardoso <FranciscoCardoso913@users.noreply.github.com>
…after validating the application
…ng of pending offers depending on application status Co-authored-by: Francisco Cardoso <FranciscoCardoso913@users.noreply.github.com>
…s approved Co-authored-by: Francisco Cardoso <FranciscoCardoso913@users.noreply.github.com>
…ers. Co-authored-by: Francisco Cardoso <FranciscoCardoso913@users.noreply.github.com>
Co-authored-by: Daniel Ferreira <dsantosferreira@users.noreply.github.com>
Co-authored-by: Daniel Ferreira <dsantosferreira@users.noreply.github.com>
Co-authored-by: Daniel Ferreira <dsantosferreira@users.noreply.github.com>
…ing the type of errors some functions throw Co-authored-by: Daniel Ferreira <dsantosferreira@users.noreply.github.com>
Co-authored-by: Daniel Ferreira <dsantosferreira@users.noreply.github.com>
…the auth/recover/:token/confirm endpoint Co-authored-by: Daniel Ferreira <dsantosferreira@users.noreply.github.com>
…plications/company/:id/reject
…plication Co-authored-by: Daniel Ferreira <dsantosferreira@users.noreply.github.com>
… to previously uncover parts
5d65bf9 to
b193933
Compare
| return next(); | ||
| } catch (jwtErr) { | ||
| if (jwtErr.name === "TokenExpiredError") { | ||
| return next(new APIError(HTTPStatus.GONE, ErrorTypes.FORBIDDEN, ValidationReasons.EXPIRED_TOKEN)); |
There was a problem hiding this comment.
Why gone? This should just be forbidden, no?
"The HyperText Transfer Protocol (HTTP) 410 Gone client error response code indicates that access to the target resource is no longer available at the origin server and that this condition is likely to be permanent."
There was a problem hiding this comment.
@FranciscoCardoso913 did you give an explanation regarding this?
| await Account.create({ | ||
| email, | ||
| password, | ||
| password: (password), |
There was a problem hiding this comment.
It was an accident
There was a problem hiding this comment.
@FranciscoCardoso913 this does not seem to have changed, was it a typo or not?
…one is updated instead of being deleted and replaced
| async updateOrCreate(query, update) { | ||
| let application = await CompanyApplication.findOne(query); | ||
| if (!application) application = await this.create(update); | ||
| else application = await CompanyApplication.findOneAndUpdate(query, update, { new: true }); |
Check failure
Code scanning / CodeQL
Database query built from user-controlled sources
…irmation-email-when-companies-register
df467c5 to
4f35451
Compare
Naapperas
left a comment
There was a problem hiding this comment.
Most of the comments I made serve as introductions for discussion, not necessarily requested changes. There are some, however, hence this.
Besides this, I just remembered something: what is the behavior of offers belonging to a company that gains full access to NIJobs if there are more than the allowed amount of concurrent offers pending? (I might have forgotten, sorry 🥲)
| return next(); | ||
| } catch (jwtErr) { | ||
| if (jwtErr.name === "TokenExpiredError") { | ||
| return next(new APIError(HTTPStatus.GONE, ErrorTypes.FORBIDDEN, ValidationReasons.EXPIRED_TOKEN)); |
There was a problem hiding this comment.
@FranciscoCardoso913 did you give an explanation regarding this?
There was a problem hiding this comment.
I just thought of something: although the token was generated as part of the process of a company applying to use NIJobs, the token itself is not part of the company. As such, I would suggest restructuring the code a bit, following the comments I'll be leaving next.
The general idea is that a token is part of an application but not a company, so having /apply/company/:token seemed a bit odd to me. What do you think?
There was a problem hiding this comment.
Feel free to ignore the following comments if you don't agree with this opinion, given that you reason about it.
| */ | ||
| router.post("/", validators.create, async (req, res, next) => { | ||
|
|
||
| router.post("/", validators.create, applicationMiddleware.exceededCreationTimeLimit, async (req, res, next) => { |
There was a problem hiding this comment.
| router.post("/", validators.create, applicationMiddleware.exceededCreationTimeLimit, async (req, res, next) => { | |
| router.post("/company", validators.create, applicationMiddleware.exceededCreationTimeLimit, async (req, res, next) => { |
I cannot edit unmodified lines but above, on line 12, it should become:
app.use("/apply", router);This change should not break existing functionality/tests.
| /** | ||
| * Validates application | ||
| */ | ||
| router.post("/:token/validate", validators.finishValidation, validToken, async (req, res, next) => { |
There was a problem hiding this comment.
All tests that hit this route should take into account the change made on the comment above.
| const account = await Account.findOne({ company: req.targetOwner }); | ||
| const application = await CompanyApplication.findOne({ email: account.email }); |
There was a problem hiding this comment.
On way for this to "look cleaner" is if the "pending" state could be computed from the account object itself. Take a look at Mongoose Schema Virtuals and see if you agree with this.
There was a problem hiding this comment.
Also, maybe this could be hidden behind a service call? Don't we have an AccountService ?
| try { | ||
| const { account } = await (new ApplicationService()).approve(req.params.id); | ||
| const account = await (new ApplicationService()).approve(req.params.id); | ||
| const company = await Company.findOne({ _id: account.company }); |
There was a problem hiding this comment.
Same thing as last comment.
| <h1>We are delighted to have you on board, {{companyName}}!</h1> | ||
| <p>We are pleased to inform you that your application has been accepted, and all the offers | ||
| you have created so far are now visible to the public!</p> | ||
| <p>Going forward, any offer you create will be immediately visible to the public audience.</p> |
There was a problem hiding this comment.
I believe that, although companies should already know this, we should warn them about our imposed limits on concurrent offers.
| <p>We will now review your application to determine the trustworthiness of your company. | ||
| In the meantime, you can complete your registration by logging into your account and begin creating offers. | ||
| Please note that your offers will remain hidden from the public until your company is approved.</p> | ||
| <p>Your Application ID is {{applicationId}} and you registered {{companyName}}.</p> |
| return null; | ||
| } | ||
| }; | ||
| export const verifyAndDecodeToken = (token, secret) => jwt.verify(token, secret, { algorithm: "HS256" }); |
There was a problem hiding this comment.
Why did you move the error handling logic out of this method? I recall you returning different errors based on the thrown exception. Couldn't we abstract those jwt exceptions into our custom, more semantic, ones? Food for thought.
There was a problem hiding this comment.
I agree with this comment, I think the error handling error should be inside and outside a simpler null check
| await Account.create({ | ||
| email, | ||
| password, | ||
| password: (password), |
There was a problem hiding this comment.
@FranciscoCardoso913 this does not seem to have changed, was it a typo or not?
|
Some of the comments appear outdated and I don't know why: when I open the respective files nothing changed. Please resolve or answer the conversations as if they were not outdated. |
DoStini
left a comment
There was a problem hiding this comment.
As of my comments, everything seems to be fine. Before merging address the comments @Naapperas suggested
Confirmation email when companies register
Important:
Although this is a back-end issue it also has changes in the Front-End! See the changes made in the Front-End here: NIAEFEUP/nijobs-fe#309
Issue: #224
Discussed solution:
Back-End changes:
Emails new order:
What is yet to be done:
Doubts: