diff --git a/src/entities/User.ts b/src/entities/User.ts index 787c5e0..4808482 100644 --- a/src/entities/User.ts +++ b/src/entities/User.ts @@ -25,10 +25,10 @@ export interface UserInterface { phoneNumber: string; photoUrl?: string; verified?: boolean; + twoFactorEnabled?: boolean; status?: 'active' | 'suspended'; userType: 'Admin' | 'Buyer' | 'Vendor'; role?: string; - twoFactorEnabled?: boolean; twoFactorCode?: string; twoFactorCodeExpiresAt?: Date; createdAt?: Date; @@ -119,7 +119,7 @@ export class User { feedbacks!: Feedback[]; @BeforeInsert() - setRole (): void { + setRole(): void { this.role = this.userType === 'Vendor' ? roles.vendor : roles.buyer; } } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index d689c27..377e419 100644 --- a/src/index.ts +++ b/src/index.ts @@ -28,7 +28,7 @@ app.use(passport.initialize()); app.use(passport.session()); app.use(express.json()); app.use(cookieParser()); -app.use(cors({ origin: '*' })); +app.use(cors({ origin: process.env.CLIENT_URL, credentials: true })); app.use(router); addDocumentation(app); app.all('*', (req: Request, res: Response, next) => { diff --git a/src/routes/ProductRoutes.ts b/src/routes/ProductRoutes.ts index 49a6c5e..0faba97 100644 --- a/src/routes/ProductRoutes.ts +++ b/src/routes/ProductRoutes.ts @@ -18,7 +18,7 @@ import { createOrder, getOrders, getOrder, updateOrder, - getOrdersHistory,Payment, + getOrdersHistory, Payment, getSingleVendorOrder, getVendorOrders, updateVendorOrder, diff --git a/src/routes/UserRoutes.ts b/src/routes/UserRoutes.ts index ad25a36..20ba2b2 100644 --- a/src/routes/UserRoutes.ts +++ b/src/routes/UserRoutes.ts @@ -20,6 +20,10 @@ import { hasRole } from '../middlewares/roleCheck'; import { isTokenValide } from '../middlewares/isValid'; import passport from 'passport'; import '../utils/auth'; +import { start2FAProcess } from '../services/userServices/userStartTwoFactorAuthProcess'; +import { otpTemplate } from '../helper/emailTemplates'; +import { sendOTPEmail } from '../services/userServices/userSendOTPEmail'; +import { sendOTPSMS } from '../services/userServices/userSendOTPMessage'; import { authMiddleware } from '../middlewares/verifyToken'; const router = Router(); @@ -41,29 +45,52 @@ router.get('/google-auth', passport.authenticate('google', { scope: ['profile', router.get( '/auth/google/callback', passport.authenticate('google', { - successRedirect: '/user/login/success', - failureRedirect: '/user/login/failed', + successRedirect: `${process.env.CLIENT_URL}/login/google-auth`, + failureRedirect: `${process.env.CLIENT_URL}/login/google-auth`, }) ); router.get('/login/success', async (req, res) => { const user = req.user as UserInterface; + if (!user) { responseError(res, 404, 'user not found'); + return; + } + + if (user.status === 'suspended') { + return res.status(400).json({ status: 'error', message: 'Your account has been suspended' }); } - const payload = { - id: user?.id, - email: user?.email, - role: user?.role, - }; - const token = jwt.sign(payload, process.env.JWT_SECRET as string, { expiresIn: '24h' }); - res.status(200).json({ + + if (!user.twoFactorEnabled) { + const payload = { + id: user?.id, + firstName: user.firstName, + lastName: user.lastName, + email: user?.email, + role: user?.role, + }; + const token = jwt.sign(payload, process.env.JWT_SECRET as string, { expiresIn: '24h' }); + return res.status(200).json({ + status: 'success', + data: { + token: token, + message: 'Login success', + }, + }); + } + const otpCode = await start2FAProcess(user.email); + const OTPEmailcontent = otpTemplate(user.firstName, otpCode.toString()); + await sendOTPEmail('Login OTP Code', user.email, OTPEmailcontent); + await sendOTPSMS(user.phoneNumber, otpCode.toString()); + return res.status(200).json({ status: 'success', data: { - token: token, - message: 'Login success', + email: user.email, + message: 'Please provide the OTP sent to your email or phone', }, }); }); + router.get('/login/failed', async (req, res) => { res.status(401).json({ status: false, diff --git a/src/services/userServices/userLoginService.ts b/src/services/userServices/userLoginService.ts index 57633d0..fa30bbd 100644 --- a/src/services/userServices/userLoginService.ts +++ b/src/services/userServices/userLoginService.ts @@ -42,8 +42,10 @@ export const userLoginService = async (req: Request, res: Response) => { const token = jwt.sign( { id: user.id, + firstName: user.firstName, + lastName: user.lastName, email: user.email, - userType: user.userType, + role: user.role, }, process.env.JWT_SECRET as string, { expiresIn: '24h' } @@ -71,6 +73,7 @@ export const userLoginService = async (req: Request, res: Response) => { return res.status(200).json({ status: 'success', data: { + email: user.email, message: 'Please provide the OTP sent to your email or phone', }, }); diff --git a/src/services/userServices/userProfileUpdateServices.ts b/src/services/userServices/userProfileUpdateServices.ts index 82fb71d..f5d4b30 100644 --- a/src/services/userServices/userProfileUpdateServices.ts +++ b/src/services/userServices/userProfileUpdateServices.ts @@ -2,8 +2,7 @@ import { Request, Response } from 'express'; import { responseError, responseSuccess } from '../../utils/response.utils'; import { User, UserInterface } from '../../entities/User'; import { getRepository } from 'typeorm'; -import { userProfileUpdate } from '../../controllers/authController'; - +import { userProfileUpdate } from '../../controllers/authController' export const userProfileUpdateServices = async (req: Request, res: Response) => { try { diff --git a/src/services/userServices/userValidateOTP.ts b/src/services/userServices/userValidateOTP.ts index c26003f..7dce921 100644 --- a/src/services/userServices/userValidateOTP.ts +++ b/src/services/userServices/userValidateOTP.ts @@ -26,8 +26,10 @@ export const userValidateOTP = async (req: Request, res: Response) => { const token = jwt.sign( { id: user?.id, + firstName: user?.firstName, + lastName: user?.lastName, email: user?.email, - userType: user?.userType, + role: user?.role, }, process.env.JWT_SECRET as string, { expiresIn: '24h' } diff --git a/src/utils/auth.ts b/src/utils/auth.ts index 623883f..f09ca47 100644 --- a/src/utils/auth.ts +++ b/src/utils/auth.ts @@ -5,12 +5,13 @@ import { User } from '../entities/User'; import { getRepository } from 'typeorm'; import bcrypt from 'bcrypt'; import '../utils/auth'; +import { v4 as uuid } from 'uuid'; passport.use( new Strategy( { clientID: process.env.GOOGLE_CLIENT_ID as string, clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, - callbackURL: 'http://localhost:6890/user/auth/google/callback/', + callbackURL: `http://localhost:${process.env.PORT || 8000}/user/auth/google/callback/`, scope: ['email', 'profile'], }, async (accessToken: any, refreshToken: any, profile: any, cb: any) => { @@ -27,7 +28,7 @@ passport.use( return await cb(null, existingUser); } const saltRounds = 10; - const hashedPassword = await bcrypt.hash('password', saltRounds); + const hashedPassword = await bcrypt.hash(uuid(), saltRounds); const newUser = new User(); newUser.firstName = givenName; newUser.lastName = family_name ?? familyName ?? 'undefined';