-
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.
- Loading branch information
Showing
13 changed files
with
185 additions
and
64 deletions.
There are no files selected for viewing
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 |
---|---|---|
@@ -1,7 +1,7 @@ | ||
export const UNKNOWN_ERR = 'Unknown error'; | ||
export const INCORRECT_USERNAME_OR_PASSWORD = 'Incorrect username or password'; | ||
export const INCORRECT_EMAIL_OR_PASSWORD = 'Incorrect email or password'; | ||
export const INVALID_EMAIL_VERIFICATION_TOKEN = 'Invalid email verification token'; | ||
export const EXPIRED_EMAIL_VERIFICATION_TOKEN = 'Expired email verification token'; | ||
export const INVALID_TOKEN = 'Invalid token'; | ||
export const EXPIRED_TOKEN = 'Expired token'; | ||
|
||
export class EmailVerificationTokenError extends Error {} |
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 |
---|---|---|
@@ -1,24 +1,51 @@ | ||
import { transporter } from '../config/email.ts'; | ||
import { TOKEN_TYPE } from '../models/tokenManger.ts'; | ||
|
||
function buildTokenOpts(email: string, token: string, tokenType: TOKEN_TYPE) { | ||
let endPoint; | ||
let msg; | ||
let subject; | ||
|
||
export const sendEmailVerificationLink = (email: string, token: string) => { | ||
const domainURL = process.env.DOMAIN_URL!; | ||
const url = `${domainURL}/email-verification/${token}`; | ||
const msg = 'Click Here to Verify Your Account'; | ||
|
||
const mailOpts = { | ||
// eslint-disable-next-line default-case | ||
switch (tokenType) { | ||
case 'email_verification': | ||
endPoint = 'email-verification'; | ||
msg = 'Click Here to Verify Your Account'; | ||
subject = 'Verify Your Account Now'; | ||
break; | ||
case 'password_reset': | ||
endPoint = 'password-reset'; | ||
msg = 'Click Here to Reset Your Password'; | ||
subject = 'Reset Your Password'; | ||
break; | ||
} | ||
const url = `${domainURL}/${endPoint}/${token}`; | ||
|
||
return { | ||
from: process.env.SMTP_USER!, | ||
to: email, | ||
subject: 'Verify Your Account Now', | ||
subject, | ||
text: `${url} ${msg}`, | ||
html: `<a href=${url}>${msg}</a>`, | ||
}; | ||
} | ||
|
||
const sendTokenLink = (email: string, token: string, tokenType: TOKEN_TYPE) => { | ||
const emailOpts = buildTokenOpts(email, token, tokenType); | ||
transporter | ||
.sendMail(mailOpts) | ||
.sendMail(emailOpts) | ||
.then((info) => { | ||
console.log(`Email sent: ${info.messageId}`); | ||
}) | ||
.catch((err) => { | ||
console.error(err); | ||
}); | ||
}; | ||
|
||
export const sendEmailVerificationLink = (email: string, token: string) => | ||
sendTokenLink(email, token, 'email_verification'); | ||
|
||
export const sendPasswordResetLink = (email: string, token: string) => | ||
sendTokenLink(email, token, 'password_reset'); |
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 |
---|---|---|
@@ -1,4 +1,93 @@ | ||
import { Router } from 'express'; | ||
import { eq } from 'drizzle-orm'; | ||
import { | ||
passwordResetSchema, | ||
requestPasswordResetSchema, | ||
} from '../validator/user.ts'; | ||
import { | ||
buildClientErrorResponse, | ||
buildUnknownErrorResponse, | ||
} from '../lib/utils.ts'; | ||
import { db } from '../db/db.ts'; | ||
import { user } from '../schema/user.ts'; | ||
import { passwordResetTM } from '../models/tokenManger.ts'; | ||
import { sendPasswordResetLink } from '../lib/email.ts'; | ||
import { auth } from '../db/lucia.ts'; | ||
import { EXPIRED_TOKEN, INVALID_TOKEN } from '../constant/error.ts'; | ||
|
||
const router = Router(); | ||
router.post('/password-reset', async (req, res) => { | ||
const parseRes = requestPasswordResetSchema.safeParse(req.body); | ||
if (!parseRes.success) { | ||
const formatted = parseRes.error.format(); | ||
if (formatted.email) { | ||
return buildClientErrorResponse(res, 'Invalid Email'); | ||
} | ||
return buildUnknownErrorResponse(res); | ||
} | ||
const { email } = parseRes.data; | ||
|
||
try { | ||
const storedUser = await db.query.user.findFirst({ | ||
where: eq(user.email, email), | ||
}); | ||
|
||
if (!storedUser) { | ||
return buildClientErrorResponse(res, 'User does not exist'); | ||
} | ||
const token = await passwordResetTM.generate(storedUser.id); | ||
sendPasswordResetLink(email, token); | ||
|
||
return res.send(); | ||
} catch (e) { | ||
if (e instanceof Error) { | ||
console.error(e); | ||
} | ||
return buildUnknownErrorResponse(res); | ||
} | ||
}); | ||
|
||
router.post('/password-reset/:token', async (req, res) => { | ||
const parseRes = passwordResetSchema.safeParse(req.body); | ||
if (!parseRes.success) { | ||
const formatted = parseRes.error.format(); | ||
if (formatted.password) { | ||
return buildClientErrorResponse(res, formatted.password._errors); | ||
} | ||
return buildUnknownErrorResponse(res); | ||
} | ||
|
||
const { password } = parseRes.data; | ||
try { | ||
const { token } = req.params; | ||
const userId = await passwordResetTM.validate(token); | ||
const userFound = await auth.getUser(userId); | ||
|
||
await auth.invalidateAllUserSessions(userFound.userId); | ||
await auth.updateKeyPassword('email', userFound.email, password); | ||
const session = await auth.createSession({ | ||
userId: userFound.userId, | ||
attributes: {}, | ||
}); | ||
const authRequest = auth.handleRequest(req, res); | ||
authRequest.setSession(session); | ||
return res.json({ | ||
redirectTo: '/', | ||
}); | ||
} catch (e) { | ||
if (e instanceof Error) { | ||
switch (e.message) { | ||
case INVALID_TOKEN: | ||
return buildClientErrorResponse(res, INVALID_TOKEN); | ||
case EXPIRED_TOKEN: | ||
return buildClientErrorResponse(res, EXPIRED_TOKEN); | ||
default: | ||
return buildUnknownErrorResponse(res); | ||
} | ||
} | ||
console.error(e); | ||
return buildUnknownErrorResponse(res); | ||
} | ||
}); | ||
|
||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Router } from 'express'; | ||
import signupRouter from './signup.ts'; | ||
import loginRouter from './login.ts'; | ||
import logoutRouter from './logout.ts'; | ||
import emailVerificationRouter from './resendVerification.ts'; | ||
import passwordResetRouter from './passwordReset.ts'; | ||
|
||
const router = Router(); | ||
const ROOT = '/'; | ||
|
||
router | ||
.use(ROOT, signupRouter) | ||
.use(ROOT, loginRouter) | ||
.use(ROOT, logoutRouter) | ||
.use(ROOT, emailVerificationRouter) | ||
.use(ROOT, passwordResetRouter); | ||
|
||
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 was deleted.
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