Enhance error handling in admin , user , wallet module

master
nicekid1 1 month ago
parent b48758676e
commit 49507ada65
  1. 10
      src/admin/admin.controller.ts
  2. 40
      src/admin/admin.service.ts
  3. 35
      src/cart/cart.service.ts
  4. 11
      src/invoice/invoice.service.ts
  5. 10
      src/users/users.controller.ts
  6. 34
      src/users/users.service.ts
  7. 24
      src/wallet/wallet.service.ts

@ -15,7 +15,7 @@ export class AdminController {
} }
//login as admin //login as admin
@Post("login") @Post("login")
async login(@Body() loginAdminDto: LoginAdminDto): Promise<{ accessToken }> { async login(@Body() loginAdminDto: LoginAdminDto): Promise<{ accessToken; refreshToken }> {
return this.adminService.login(loginAdminDto); return this.adminService.login(loginAdminDto);
} }
//logout user //logout user
@ -26,11 +26,9 @@ export class AdminController {
return this.adminService.logout(userId); return this.adminService.logout(userId);
} }
//get a new access token //get a new access token
@UseGuards(RoleGuard) @Post("new-token")
@Get("new-token") async newAccessToken(@Body("token") token: string) {
async newAccessToken(@Request() req) { return this.adminService.newAccessToken(token);
const userId = req.user.id
return this.adminService.refreshToken(userId);
} }
//edit admin profile //edit admin profile
@UseGuards(RoleGuard) @UseGuards(RoleGuard)

@ -17,15 +17,31 @@ export class AdminService {
//register method //register method
async register(createAdminDto: CreateAdminDto): Promise<{ message }> { async register(createAdminDto: CreateAdminDto): Promise<{ message }> {
try { try {
const existingAdmin = await this.adminModel.findOne({ const existingAdminByEmail = await this.adminModel.findOne({
where: { email: createAdminDto.email }, where: { email: createAdminDto.email },
}); });
if (existingAdmin) { if (existingAdminByEmail) {
throw new HttpException("The provided email is already registered.", HttpStatus.CONFLICT); throw new HttpException("The provided email is already registered.", HttpStatus.CONFLICT);
} }
const existingAdminByUsername = await this.adminModel.findOne({
where: { username: createAdminDto.username },
});
if (existingAdminByUsername) {
throw new HttpException("The provided username is already taken.", HttpStatus.CONFLICT);
}
const existingAdminByPhoneNumber = await this.adminModel.findOne({
where: { phoneNumber: createAdminDto.phoneNumber },
});
if (existingAdminByPhoneNumber) {
throw new HttpException("The provided phone number is already registered.", HttpStatus.CONFLICT);
}
createAdminDto.password = await bcrypt.hash(createAdminDto.password, 10); createAdminDto.password = await bcrypt.hash(createAdminDto.password, 10);
await this.adminModel.create(createAdminDto); await this.adminModel.create(createAdminDto);
return { message: "admin register is successful" }; return { message: "Admin registration is successful." };
} catch (error) { } catch (error) {
if (error instanceof HttpException) { if (error instanceof HttpException) {
throw error; throw error;
@ -34,14 +50,14 @@ export class AdminService {
} }
} }
//login method //login method
async login(loginAdminDto: LoginAdminDto): Promise<{ accessToken: string }> { async login(loginAdminDto: LoginAdminDto): Promise<{ accessToken: string; refreshToken: string }> {
try { try {
const admin = await this.adminModel.findOne({ const admin = await this.adminModel.findOne({
where: { email: loginAdminDto.email }, where: { email: loginAdminDto.email,username:loginAdminDto.username },
}); });
if (!admin) { if (!admin) {
throw new HttpException("Invalid email or password.", HttpStatus.UNAUTHORIZED); throw new HttpException("Invalid email, username or password.", HttpStatus.UNAUTHORIZED);
} }
const isValidPassword = await bcrypt.compare(loginAdminDto.password, admin.password); const isValidPassword = await bcrypt.compare(loginAdminDto.password, admin.password);
@ -69,7 +85,7 @@ export class AdminService {
{ where: { id: admin.id } }, { where: { id: admin.id } },
); );
return { accessToken }; return { accessToken, refreshToken };
} catch (error) { } catch (error) {
if (error instanceof HttpException) { if (error instanceof HttpException) {
throw error; throw error;
@ -94,16 +110,14 @@ export class AdminService {
} }
} }
//getting new access token //getting new access token
async refreshToken(userId: number): Promise<{ accessToken: string }> { async newAccessToken(refreshToken: string) {
const refreshToken = (await this.adminModel.findOne({ where: { id: userId } })).refreshToken;
if (!refreshToken) { if (!refreshToken) {
throw new HttpException("Refresh token is required.", HttpStatus.BAD_REQUEST); throw new HttpException("Refresh token is required.", HttpStatus.BAD_REQUEST);
} }
let decoded; let decoded;
try { try {
decoded = this.jwtService.verify(refreshToken, { secret: process.env.JWT_REFRESH_SECRET }); decoded = this.jwtService.verify(refreshToken, { secret: this.configService.get<string>("JWT_REFRESH_SECRET") });
} catch (error) { } catch (error) {
throw new HttpException("Invalid or expired token.", HttpStatus.UNAUTHORIZED); throw new HttpException("Invalid or expired token.", HttpStatus.UNAUTHORIZED);
} }
@ -113,8 +127,8 @@ export class AdminService {
throw new HttpException("User not found.", HttpStatus.NOT_FOUND); throw new HttpException("User not found.", HttpStatus.NOT_FOUND);
} }
if (user.role !== "admin") { if (user.refreshToken !== refreshToken) {
throw new HttpException("You are not authorized to get an admin token.", HttpStatus.FORBIDDEN); throw new HttpException("Invalid refresh token.", HttpStatus.FORBIDDEN);
} }
const accessToken = this.jwtService.sign( const accessToken = this.jwtService.sign(

@ -77,29 +77,47 @@ export class CartService {
include: [ include: [
{ {
model: Product, model: Product,
attributes: ["name"], attributes: ["name", "price"],
}, },
], ],
}); });
if (!cartItems || cartItems.length === 0) { if (!cartItems || cartItems.length === 0) {
throw new HttpException("No cart items found for the specified user.", HttpStatus.NOT_FOUND); return { cartItems: [], totalPrice: 0 };
} }
const totalPrice = cartItems.reduce((sum, item) => sum + (Number(item.productPrice) * item.quantity || 0), 0); const totalPrice = cartItems.reduce((sum, item) => {
return sum + (Number(item.productPrice) * item.quantity || 0);
}, 0);
return { cartItems, totalPrice }; return { cartItems, totalPrice };
} catch (error) { } catch (error) {
throw new HttpException("An unexpected error occurred while fetching the cart. Please try again later.", HttpStatus.INTERNAL_SERVER_ERROR); console.error("Error fetching cart items:", error);
throw new HttpException(
"An unexpected error occurred while fetching the cart. Please try again later.",
HttpStatus.INTERNAL_SERVER_ERROR
);
} }
} }
// Update cart item quantity // Update cart item quantity
async updateCart(userId: number, productId: number, quantity: number): Promise<Cart> { async updateCart(userId: number, productId: number, quantity: number): Promise<Cart> {
const cartItem = await this.cartModel.findOne({ where: { userId, productId, status: "open" } }); const cartItem = await this.cartModel.findOne({ where: { userId, productId, status: "open" } });
if (!cartItem) { if (!cartItem) {
throw new HttpException("Product not found in the cart.", HttpStatus.NOT_FOUND); throw new HttpException("Product not found in the cart.", HttpStatus.NOT_FOUND);
} }
const product = await this.productModel.findByPk(productId);
if (!product) {
throw new HttpException("Product not found.", HttpStatus.NOT_FOUND);
}
if (product.quantity < quantity) {
throw new HttpException("Insufficient product quantity.", HttpStatus.CONFLICT);
}
try { try {
cartItem.quantity = quantity; cartItem.quantity = quantity;
await cartItem.save(); await cartItem.save();
@ -127,11 +145,14 @@ export class CartService {
//delete whole cart by user //delete whole cart by user
async clearCart(userId: number) { async clearCart(userId: number) {
await this.cartModel.destroy({ where: { userId } }); await this.cartModel.destroy({
return { message: "cart cleared successful" }; where: { userId, status: 'open' },
});
return { message: "Cart cleared successfully" };
} }
//order(clearCart disable)
//order
async processOrder(userId: number, totalAmount: number): Promise<{ message: string; invoice: Invoice }> { async processOrder(userId: number, totalAmount: number): Promise<{ message: string; invoice: Invoice }> {
try { try {
const carts = await this.cartModel.findAll({ where: { userId, status: "open" } }); const carts = await this.cartModel.findAll({ where: { userId, status: "open" } });

@ -17,11 +17,22 @@ export class InvoiceService {
if (!user) { if (!user) {
throw new HttpException("User not found", HttpStatus.NOT_FOUND); throw new HttpException("User not found", HttpStatus.NOT_FOUND);
} }
try {
const invoice = await this.invoiceModel.create({ const invoice = await this.invoiceModel.create({
userId, userId,
totalPaymentAmount: 0, totalPaymentAmount: 0,
}); });
if (!invoice) {
throw new HttpException("Failed to create invoice", HttpStatus.INTERNAL_SERVER_ERROR);
}
return invoice; return invoice;
} catch (error) {
console.error("Error during invoice creation:", error);
throw new HttpException("An error occurred while creating the invoice.", HttpStatus.INTERNAL_SERVER_ERROR);
}
} }
async updateTotalPayment(userId: number) { async updateTotalPayment(userId: number) {
const user = await User.findByPk(userId); const user = await User.findByPk(userId);

@ -17,15 +17,13 @@ export class UsersController {
} }
//login as user //login as user
@Post("login") @Post("login")
async login(@Body() loginUserDto: LoginUserDto): Promise<{ accessToken }> { async login(@Body() loginUserDto: LoginUserDto): Promise<{ accessToken; refreshToken }> {
return this.usersService.login(loginUserDto); return this.usersService.login(loginUserDto);
} }
//get access token //get access token
@UseGuards(JwtAuthGuard) @Post("new-token")
@Get("new-token") async newAccessToken(@Body("token") token: string) {
async newAccessToken(@Request() req) { return this.usersService.newAccessToken(token);
const userId = req.user.id;
return this.usersService.newAccessToken(userId);
} }
//logout user //logout user
@UseGuards(JwtAuthGuard) @UseGuards(JwtAuthGuard)

@ -35,10 +35,18 @@ export class UsersService {
throw new BadRequestException("Phone number is already registered."); throw new BadRequestException("Phone number is already registered.");
} }
const usernameExists = await this.userModel.findOne({
where: { username: createUserDto.username },
});
if (usernameExists) {
throw new BadRequestException("Username is already registered.");
}
await this.userModel.create(createUserDto); await this.userModel.create(createUserDto);
const user = await this.userModel.findOne({ const user = await this.userModel.findOne({
where: { email: createUserDto.email }, where: { email: createUserDto.email },
}); });
const refreshToken = this.jwtService.sign( const refreshToken = this.jwtService.sign(
{ id: user.id }, { id: user.id },
{ {
@ -48,7 +56,7 @@ export class UsersService {
); );
await this.userModel.update( await this.userModel.update(
{ refreshToken }, // { refreshToken },
{ where: { id: user.id } }, { where: { id: user.id } },
); );
@ -61,14 +69,14 @@ export class UsersService {
} }
} }
// Login method // Login method
async login(loginUserDto: LoginUserDto): Promise<{ accessToken: string }> { async login(loginUserDto: LoginUserDto): Promise<{ accessToken: string , refreshToken:string}> {
try { try {
const user = await this.userModel.findOne({ const user = await this.userModel.findOne({
where: { email: loginUserDto.email }, where: { email: loginUserDto.email, username:loginUserDto.username },
}); });
if (!user) { if (!user) {
throw new UnauthorizedException("Invalid email or password."); throw new UnauthorizedException("Invalid email , username or password.");
} }
const passwordMatch = await bcrypt.compare(loginUserDto.password, user.password); const passwordMatch = await bcrypt.compare(loginUserDto.password, user.password);
@ -97,7 +105,7 @@ export class UsersService {
{ where: { id: user.id } }, { where: { id: user.id } },
); );
return { accessToken: accessToken }; return { accessToken, refreshToken };
} catch (error) { } catch (error) {
if (error instanceof HttpException) { if (error instanceof HttpException) {
throw error; throw error;
@ -106,21 +114,25 @@ export class UsersService {
} }
} }
// getting access token // getting access token
async newAccessToken(userId: number) { async newAccessToken(refreshToken: string) {
const user = await this.userModel.findOne({ where: { id: userId } }); if (!refreshToken) {
if (!user || !user.refreshToken) {
throw new HttpException("Refresh token is required.", HttpStatus.BAD_REQUEST); throw new HttpException("Refresh token is required.", HttpStatus.BAD_REQUEST);
} }
let decoded; let decoded;
try { try {
decoded = this.jwtService.verify(user.refreshToken, { secret: process.env.JWT_REFRESH_SECRET }); decoded = this.jwtService.verify(refreshToken, { secret: this.configService.get<string>("JWT_REFRESH_SECRET") });
} catch (error) { } catch (error) {
throw new HttpException("Invalid or expired token.", HttpStatus.UNAUTHORIZED); throw new HttpException("Invalid or expired token.", HttpStatus.UNAUTHORIZED);
} }
if (user.id !== decoded.id) { const user = await this.getProfile(decoded.id);
throw new HttpException("User ID mismatch.", HttpStatus.FORBIDDEN); if (!user) {
throw new HttpException("User not found.", HttpStatus.NOT_FOUND);
}
if (user.refreshToken !== refreshToken) {
throw new HttpException("Invalid refresh token.", HttpStatus.FORBIDDEN);
} }
const accessToken = this.jwtService.sign( const accessToken = this.jwtService.sign(

@ -27,8 +27,7 @@ export class WalletService {
const wallet = await this.walletModel.findOne({ where: { userId } }); const wallet = await this.walletModel.findOne({ where: { userId } });
if (!wallet) { if (!wallet) {
const newWallet = await this.walletModel.create({ userId, balance: 0 }); throw new HttpException('Wallet not found!', HttpStatus.NOT_FOUND)
return { walletId: newWallet.id, userId: newWallet.userId, balance: newWallet.balance };
} }
return { balance: wallet.balance }; return { balance: wallet.balance };
@ -54,28 +53,37 @@ export class WalletService {
const wallet = await this.walletModel.findOne({ where: { userId } }); const wallet = await this.walletModel.findOne({ where: { userId } });
if (!wallet) { if (!wallet) {
throw new Error("Wallet not found"); throw new HttpException("Wallet not found", HttpStatus.NOT_FOUND);
} }
if (wallet.balance < amount) { if (wallet.balance < amount) {
throw new Error("Insufficient funds"); throw new HttpException("Insufficient funds", HttpStatus.BAD_REQUEST);
} }
try {
wallet.balance -= amount; wallet.balance -= amount;
await this.transactionModel.create({ await this.transactionModel.create({
walletId: wallet.id, walletId: wallet.id,
amount: String(amount).startsWith("-") ? String(amount) : `-${amount}`, amount: `-${amount}`,
}); });
await wallet.save(); await wallet.save();
return "Payment processed successfully"; return "Payment processed successfully";
} catch (error) {
console.error("Error processing payment:", error.message);
throw new HttpException("An error occurred while processing the payment.", HttpStatus.INTERNAL_SERVER_ERROR);
}
} }
//getting transaction //getting transaction
async getTransactionById(userId: number) { async getTransactionById(userId: number) {
const wallet = this.getWalletInfo(userId); const wallet = await this.getWalletInfo(userId);
if (!wallet) {
throw new HttpException("Wallet not found for the user.", HttpStatus.NOT_FOUND);
}
return await this.transactionModel.findAll({ return await this.transactionModel.findAll({
where: { walletId: (await wallet).walletId }, where: { walletId: wallet.walletId },
}); });
} }
} }

Loading…
Cancel
Save