From adf1bd07d90f6858e5da9b10123ecd714fe6ad11 Mon Sep 17 00:00:00 2001 From: Carson Lin Date: Sun, 8 Oct 2023 14:59:42 -0400 Subject: [PATCH] emailverificationmodel check --- src/controllers/accountController.ts | 10 ++++++---- src/functions/createAccount.ts | 24 ------------------------ src/integration/models.ts | 9 ++------- src/routes/account.ts | 8 ++++---- views/createAccount.pug | 2 +- views/verifyEmailSuccess.pug | 9 +++++++++ 6 files changed, 22 insertions(+), 40 deletions(-) create mode 100644 views/verifyEmailSuccess.pug diff --git a/src/controllers/accountController.ts b/src/controllers/accountController.ts index 132060a..152ee5b 100644 --- a/src/controllers/accountController.ts +++ b/src/controllers/accountController.ts @@ -121,6 +121,7 @@ export class ResetCredentials { key: string; } + /** */ export class PasswordResetRequestParams extends ResetCredentials { @@ -165,21 +166,21 @@ export const verifyEmail = async (creds: ResetCredentials): PromiseRequest a new one.', }; - const resetRequest = await VerifyEmailRequestModel.findById(creds.id); - if (!resetRequest) { + const verifyRequest = await VerifyEmailRequestModel.findById(creds.id); + if (!verifyRequest) { throw new HttpException(400, { ...invalidProps, message: `Email verification ID ${creds.id} did not match any request`, }); } - if (!(await argon2.verify(resetRequest.key, creds.key as string))) { + if (!(await argon2.verify(verifyRequest.key, creds.key as string))) { throw new HttpException(400, { ...invalidProps, message: 'Email verification key did not match database', }); } - return resetRequest; + return verifyRequest; }; export const doPasswordReset = async (params: PasswordResetRequestParams) => { @@ -280,6 +281,7 @@ export const isEmailAvailable = async (email: string): Promise => { const [inDatabase, inPending] = await Promise.all([ searchAsync(ldapClient, ldapEscape.filter`(swatmail=${email})`), TaskModel.exists({ 'data.email': email, status: 'pending' }), + VerifyEmailRequestModel.exists({'data.email': email}) ]); if (inDatabase || inPending) { diff --git a/src/functions/createAccount.ts b/src/functions/createAccount.ts index 9cb019c..578575f 100644 --- a/src/functions/createAccount.ts +++ b/src/functions/createAccount.ts @@ -11,7 +11,6 @@ import { generateEmail } from '../util/emailTemplates'; import { addLdap, searchAsyncMultiple } from '../util/ldapUtils'; import { logger } from '../util/logging'; import { createPasswordResetRequest } from '../util/passwordReset'; -import { createVerifyAccountRequest } from '../util/accountVerify'; export interface CreateAccountData { username: string; @@ -97,27 +96,4 @@ export const createAccount = async (data: any) => { } else { throw new Error('CreateAccount data not properly formatted'); } - - const [verifyId, verifyKey] = await createVerifyAccountRequest(data.email, 24 * 7, true); - const [emailText, transporter] = await Promise.all([ - generateEmail('verification.html', { - email: data.email, - domain: process.env.EXTERNAL_ADDRESS, - verifyKey: verifyKey, - verifyId: verifyId, - }), - mailTransporter, - ]); - - const info = await transporter.sendMail({ - from: process.env.EMAIL_FROM, - to: data.email, - subject: 'Verify your SCCS account', - html: emailText, - }); - - const msgUrl = nodemailer.getTestMessageUrl(info); - if (msgUrl) { - logger.debug(`View message at ${msgUrl}`); - } }; diff --git a/src/integration/models.ts b/src/integration/models.ts index d10a550..c9df2a5 100644 --- a/src/integration/models.ts +++ b/src/integration/models.ts @@ -94,9 +94,8 @@ export interface VerifyEmailRequest { // username/password login flow. _id: string; key: string; - user: string; + email: string; timestamp: Date; - suppressEmail?: boolean; } const verifyEmailRequestSchema = new mongoose.Schema({ @@ -108,7 +107,7 @@ const verifyEmailRequestSchema = new mongoose.Schema({ type: String, required: true, }, - user: { + email: { type: String, required: true, index: true, // we'll search by user to invalidate previous reset requests @@ -117,10 +116,6 @@ const verifyEmailRequestSchema = new mongoose.Schema({ type: Date, expires: 0, }, - suppressEmail: { - type: Boolean, - required: false, - }, }); export const VerifyEmailRequestModel = mongoose.model( diff --git a/src/routes/account.ts b/src/routes/account.ts index 481ec28..dee6203 100644 --- a/src/routes/account.ts +++ b/src/routes/account.ts @@ -99,7 +99,7 @@ router.get( }), ); -router.get( +router.post( '/init', catchErrors(async (req, res, next) => { const { error, value } = jf.validateAsClass(req.query, controller.ResetCredentials); @@ -109,14 +109,14 @@ router.get( } // I have no idea why joiful throws a fit here but this is the necessary workaround - const verifyRequest = await controller.verifyPasswordReset( + const verifyEmail = await controller.verifyEmail( value as unknown as controller.ResetCredentials, ); - return res.render('verify email', { + return res.render('accountInit', { id: value.id, key: value.key, - username: verifyRequest.user, + email: verifyEmail.email, }); }), ); diff --git a/views/createAccount.pug b/views/createAccount.pug index b155547..374adcf 100644 --- a/views/createAccount.pug +++ b/views/createAccount.pug @@ -7,7 +7,7 @@ include include/sauce-common | SCCS accounts are available to all Swarthmore students, faculty, | and staff—and you'll still be able to access it after | graduation. - form#createForm.form-signin.needs-validation(action='/account/create', method='post', novalidate) + form#createForm.form-signin.needs-validation(action='/account/init', method='post', novalidate) .form-group.mb-3 .form-floating script(type='text/javascript'). diff --git a/views/verifyEmailSuccess.pug b/views/verifyEmailSuccess.pug new file mode 100644 index 0000000..0674b9f --- /dev/null +++ b/views/verifyEmailSuccess.pug @@ -0,0 +1,9 @@ +include include/sauce-common + ++sauce-layout('Your request has been submitted!')(hideNavbar, includeBootstrapScripts) + h1.mb-4 We've sent you an email, follow the instructions to complete setting up your SCCS account + p. + To prevent abuse, SCCS staff manually approve all account creation + requests. When classes are in session, this usually happens within a + few hours. Once you've been approved, you'll get an email at + #{ email } with a link to set your password.