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. 42
      src/admin/admin.service.ts
  3. 47
      src/cart/cart.service.ts
  4. 23
      src/invoice/invoice.service.ts
  5. 10
      src/users/users.controller.ts
  6. 44
      src/users/users.service.ts
  7. 34
      src/wallet/wallet.service.ts

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

@ -17,15 +17,31 @@ export class AdminService {
//register method
async register(createAdminDto: CreateAdminDto): Promise<{ message }> {
try {
const existingAdmin = await this.adminModel.findOne({
const existingAdminByEmail = await this.adminModel.findOne({
where: { email: createAdminDto.email },
});
if (existingAdmin) {
if (existingAdminByEmail) {
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);
await this.adminModel.create(createAdminDto);
return { message: "admin register is successful" };
return { message: "Admin registration is successful." };
} catch (error) {
if (error instanceof HttpException) {
throw error;
@ -34,14 +50,14 @@ export class AdminService {
}
}
//login method
async login(loginAdminDto: LoginAdminDto): Promise<{ accessToken: string }> {
async login(loginAdminDto: LoginAdminDto): Promise<{ accessToken: string; refreshToken: string }> {
try {
const admin = await this.adminModel.findOne({
where: { email: loginAdminDto.email },
where: { email: loginAdminDto.email,username:loginAdminDto.username },
});
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);
@ -69,7 +85,7 @@ export class AdminService {
{ where: { id: admin.id } },
);
return { accessToken };
return { accessToken, refreshToken };
} catch (error) {
if (error instanceof HttpException) {
throw error;
@ -94,27 +110,25 @@ export class AdminService {
}
}
//getting new access token
async refreshToken(userId: number): Promise<{ accessToken: string }> {
const refreshToken = (await this.adminModel.findOne({ where: { id: userId } })).refreshToken;
async newAccessToken(refreshToken: string) {
if (!refreshToken) {
throw new HttpException("Refresh token is required.", HttpStatus.BAD_REQUEST);
}
let decoded;
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) {
throw new HttpException("Invalid or expired token.", HttpStatus.UNAUTHORIZED);
}
const user = await this.adminModel.findOne({ where: { id: decoded.id } });
const user = await this.adminModel.findOne({where:{id:decoded.id}});
if (!user) {
throw new HttpException("User not found.", HttpStatus.NOT_FOUND);
}
if (user.role !== "admin") {
throw new HttpException("You are not authorized to get an admin token.", HttpStatus.FORBIDDEN);
if (user.refreshToken !== refreshToken) {
throw new HttpException("Invalid refresh token.", HttpStatus.FORBIDDEN);
}
const accessToken = this.jwtService.sign(

@ -70,36 +70,54 @@ export class CartService {
if (!userId) {
throw new HttpException("User ID is required.", HttpStatus.BAD_REQUEST);
}
try {
const cartItems = await this.cartModel.findAll({
where: { userId, status: "open" },
include: [
{
model: Product,
attributes: ["name"],
attributes: ["name", "price"],
},
],
});
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 };
} 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
async updateCart(userId: number, productId: number, quantity: number): Promise<Cart> {
const cartItem = await this.cartModel.findOne({ where: { userId, productId, status: "open" } });
if (!cartItem) {
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 {
cartItem.quantity = quantity;
await cartItem.save();
@ -109,7 +127,7 @@ export class CartService {
throw new HttpException("An unexpected error occurred while updating the cart. Please try again later.", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
// Remove an item from cart
async removeFromCart(userId: number, productId: number): Promise<{ message: string; cartItem: Cart }> {
const cartItem = await this.cartModel.findOne({ where: { userId, productId, status: "open" } });
@ -127,11 +145,14 @@ export class CartService {
//delete whole cart by user
async clearCart(userId: number) {
await this.cartModel.destroy({ where: { userId } });
return { message: "cart cleared successful" };
await this.cartModel.destroy({
where: { userId, status: 'open' },
});
return { message: "Cart cleared successfully" };
}
//order(clearCart disable)
//order
async processOrder(userId: number, totalAmount: number): Promise<{ message: string; invoice: Invoice }> {
try {
const carts = await this.cartModel.findAll({ where: { userId, status: "open" } });

@ -17,11 +17,22 @@ export class InvoiceService {
if (!user) {
throw new HttpException("User not found", HttpStatus.NOT_FOUND);
}
const invoice = await this.invoiceModel.create({
userId,
totalPaymentAmount: 0,
});
return invoice;
try {
const invoice = await this.invoiceModel.create({
userId,
totalPaymentAmount: 0,
});
if (!invoice) {
throw new HttpException("Failed to create invoice", HttpStatus.INTERNAL_SERVER_ERROR);
}
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) {
const user = await User.findByPk(userId);
@ -103,7 +114,7 @@ export class InvoiceService {
throw new HttpException("An error occurred while retrieving the invoice.", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
async getUserInvoices(userId: number){
async getUserInvoices(userId: number) {
try {
if (!userId) {
throw new HttpException("User ID are required.", HttpStatus.BAD_REQUEST);

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

@ -20,25 +20,33 @@ export class UsersService {
async register(createUserDto: CreateUserDto): Promise<{ message: string }> {
try {
createUserDto.password = await bcrypt.hash(createUserDto.password, parseInt(process.env.BCRYPT_SALT_ROUNDS || "10", 10));
const emailExists = await this.userModel.findOne({
where: { email: createUserDto.email },
});
if (emailExists) {
throw new BadRequestException("Email is already registered.");
}
const phoneExists = await this.userModel.findOne({
where: { phoneNumber: createUserDto.phoneNumber },
});
if (phoneExists) {
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);
const user = await this.userModel.findOne({
where: { email: createUserDto.email },
});
const refreshToken = this.jwtService.sign(
{ id: user.id },
{
@ -46,12 +54,12 @@ export class UsersService {
expiresIn: this.configService.get<string | number>("JWT_REFRESH_EXPIRES") || "7d",
},
);
await this.userModel.update(
{ refreshToken }, //
{ refreshToken },
{ where: { id: user.id } },
);
return { message: "User registered successfully." };
} catch (error) {
if (error instanceof HttpException) {
@ -61,14 +69,14 @@ export class UsersService {
}
}
// Login method
async login(loginUserDto: LoginUserDto): Promise<{ accessToken: string }> {
async login(loginUserDto: LoginUserDto): Promise<{ accessToken: string , refreshToken:string}> {
try {
const user = await this.userModel.findOne({
where: { email: loginUserDto.email },
where: { email: loginUserDto.email, username:loginUserDto.username },
});
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);
@ -97,7 +105,7 @@ export class UsersService {
{ where: { id: user.id } },
);
return { accessToken: accessToken };
return { accessToken, refreshToken };
} catch (error) {
if (error instanceof HttpException) {
throw error;
@ -106,21 +114,25 @@ export class UsersService {
}
}
// getting access token
async newAccessToken(userId: number) {
const user = await this.userModel.findOne({ where: { id: userId } });
if (!user || !user.refreshToken) {
async newAccessToken(refreshToken: string) {
if (!refreshToken) {
throw new HttpException("Refresh token is required.", HttpStatus.BAD_REQUEST);
}
let decoded;
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) {
throw new HttpException("Invalid or expired token.", HttpStatus.UNAUTHORIZED);
}
if (user.id !== decoded.id) {
throw new HttpException("User ID mismatch.", HttpStatus.FORBIDDEN);
const user = await this.getProfile(decoded.id);
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(

@ -27,8 +27,7 @@ export class WalletService {
const wallet = await this.walletModel.findOne({ where: { userId } });
if (!wallet) {
const newWallet = await this.walletModel.create({ userId, balance: 0 });
return { walletId: newWallet.id, userId: newWallet.userId, balance: newWallet.balance };
throw new HttpException('Wallet not found!', HttpStatus.NOT_FOUND)
}
return { balance: wallet.balance };
@ -54,28 +53,37 @@ export class WalletService {
const wallet = await this.walletModel.findOne({ where: { userId } });
if (!wallet) {
throw new Error("Wallet not found");
throw new HttpException("Wallet not found", HttpStatus.NOT_FOUND);
}
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({
walletId: wallet.id,
amount: String(amount).startsWith("-") ? String(amount) : `-${amount}`,
});
await wallet.save();
await this.transactionModel.create({
walletId: wallet.id,
amount: `-${amount}`,
});
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
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({
where: { walletId: (await wallet).walletId },
where: { walletId: wallet.walletId },
});
}
}

Loading…
Cancel
Save