From bf5d9399105977b379b23c13791d2f7ead9bd2ee Mon Sep 17 00:00:00 2001 From: JakkrapartXD Date: Fri, 30 Jan 2026 17:29:08 +0700 Subject: [PATCH] feat: add role-based frontend URL routing for password reset and email verification Add separate frontend URL environment variables for student and instructor portals. Update password reset and email verification services to route users to the appropriate frontend based on their role (INSTRUCTOR vs STUDENT). --- Backend/.env.example | 3 +++ Backend/src/services/auth.service.ts | 15 +++++++++++---- Backend/src/services/user.service.ts | 13 +++++++++---- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/Backend/.env.example b/Backend/.env.example index 1c6abbbd..150b8948 100644 --- a/Backend/.env.example +++ b/Backend/.env.example @@ -36,3 +36,6 @@ CORS_ORIGIN=http://localhost:3000 # Rate Limiting RATE_LIMIT_WINDOW_MS=900000 RATE_LIMIT_MAX_REQUESTS=100 + +FRONTEND_URL_STUDENT=http://localhost:3000 +FRONTEND_URL_INSTRUCTOR=http://localhost:3000 \ No newline at end of file diff --git a/Backend/src/services/auth.service.ts b/Backend/src/services/auth.service.ts index bdbc1d5c..ad565c93 100644 --- a/Backend/src/services/auth.service.ts +++ b/Backend/src/services/auth.service.ts @@ -261,14 +261,21 @@ export class AuthService { */ async resetRequest(email: string): Promise { try { - // Find user - const user = await prisma.user.findUnique({ where: { email } }); + // Find user with role + const user = await prisma.user.findUnique({ + where: { email }, + include: { role: true } + }); if (!user) throw new UnauthorizedError('User not found'); const token = jwt.sign({ id: user.id, email: user.email }, config.jwt.secret, { expiresIn: '1h' }); - // Create reset URL - const resetURL = `${process.env.FRONTEND_URL || 'http://localhost:3000'}/reset-password?token=${token}`; + // Create reset URL based on role + const isInstructor = user.role.code === 'INSTRUCTOR'; + const baseUrl = isInstructor + ? (process.env.FRONTEND_URL_INSTRUCTOR || 'http://localhost:3001') + : (process.env.FRONTEND_URL_STUDENT || 'http://localhost:3000'); + const resetURL = `${baseUrl}/reset-password?token=${token}`; // Create transporter const transporter = nodemailer.createTransport({ diff --git a/Backend/src/services/user.service.ts b/Backend/src/services/user.service.ts index eab882d8..6141b471 100644 --- a/Backend/src/services/user.service.ts +++ b/Backend/src/services/user.service.ts @@ -307,10 +307,11 @@ export class UserService { */ async sendVerifyEmail(token: string): Promise { try { - const decoded = jwt.verify(token, config.jwt.secret) as { id: number; email: string }; + const decoded = jwt.verify(token, config.jwt.secret) as { id: number; email: string; roleCode: string }; const user = await prisma.user.findUnique({ - where: { id: decoded.id } + where: { id: decoded.id }, + include: { role: true } }); if (!user) throw new UnauthorizedError('User not found'); @@ -323,8 +324,12 @@ export class UserService { { expiresIn: '24h' } ); - // Create verification URL - const verifyURL = `${process.env.FRONTEND_URL || 'http://localhost:3000'}/verify-email?token=${verifyToken}`; + // Create verification URL based on role + const isInstructor = user.role.code === 'INSTRUCTOR'; + const baseUrl = isInstructor + ? (process.env.FRONTEND_URL_INSTRUCTOR || 'http://localhost:3001') + : (process.env.FRONTEND_URL_STUDENT || 'http://localhost:3000'); + const verifyURL = `${baseUrl}/verify-email?token=${verifyToken}`; // Create transporter const transporter = nodemailer.createTransport({