Compare commits
5 commits
Author | SHA1 | Date | |
---|---|---|---|
e2852b6b90 | |||
12dc986941 | |||
35ca5e7e45 | |||
b5ea0a69a5 | |||
e5ad4fc0c1 |
13 changed files with 109 additions and 65 deletions
|
@ -14,26 +14,23 @@ export async function addToCart(req: Request, res: Response) {
|
||||||
res.status(400).json({ error: 'A Valid Product id is required.' });
|
res.status(400).json({ error: 'A Valid Product id is required.' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const isProductExists = await Product.exists({ _id: productId });
|
|
||||||
if (!isProductExists) {
|
let [product, cart] = await getProductAndCart(productId, userId);
|
||||||
res.status(404).json({ error: 'Product not found.' });
|
console.log(`product: ${product}, cart: ${cart}`);
|
||||||
return;
|
|
||||||
}
|
|
||||||
let cart: ICart | null = await Cart.findOne({ userId });
|
|
||||||
if (!cart) {
|
if (!cart) {
|
||||||
cart = await Cart.create({
|
cart = await Cart.create({
|
||||||
userId,
|
userId,
|
||||||
products: { [productId]: 1 },
|
products: {},
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
const currentQuantity = cart.products[productId];
|
|
||||||
if (currentQuantity === undefined) {
|
|
||||||
cart.products[productId] = 1;
|
|
||||||
} else {
|
|
||||||
cart.products[productId] += 1;
|
|
||||||
}
|
|
||||||
cart.markModified('products');
|
|
||||||
}
|
}
|
||||||
|
const currentQuantity = cart.products[productId];
|
||||||
|
if (currentQuantity === undefined) {
|
||||||
|
cart.products[productId] = 1;
|
||||||
|
} else {
|
||||||
|
cart.products[productId] += 1;
|
||||||
|
}
|
||||||
|
cart.markModified('products');
|
||||||
await cart.save();
|
await cart.save();
|
||||||
res.status(200).json({
|
res.status(200).json({
|
||||||
products: cart.products,
|
products: cart.products,
|
||||||
|
@ -44,6 +41,18 @@ export async function addToCart(req: Request, res: Response) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getProductAndCart(productId: string, userId: string) {
|
||||||
|
try {
|
||||||
|
return Promise.all([
|
||||||
|
Product.findById(productId),
|
||||||
|
Cart.findOne({ userId }),
|
||||||
|
])
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error adding product to cart:', error);
|
||||||
|
// res.status(500).json({ error: 'An error occurred while adding the product to the cart.' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function listCart(req: Request, res: Response) {
|
export async function listCart(req: Request, res: Response) {
|
||||||
try {
|
try {
|
||||||
const { userId } = req.body;
|
const { userId } = req.body;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response, NextFunction} from 'express';
|
||||||
import { Product } from '../schemas/productSchema';
|
import { Product } from '../schemas/productSchema';
|
||||||
import { createProduct, getAllProducts, getOne } from '../models/productModel';
|
import { createProduct, getAllProducts, getOne } from '../models/productModel';
|
||||||
import { ApiError } from '../utils/ApiError';
|
import { ApiError } from '../utils/ApiError';
|
||||||
|
|
||||||
const create = async (req: Request, res: Response, next) => {
|
const create = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
try {
|
try {
|
||||||
const { name, description, price } = req.body;
|
const { name, description, price } = req.body;
|
||||||
const product = await createProduct({
|
const product = await createProduct({
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response, NextFunction } from 'express';
|
||||||
import { createUser, loginUser, getAllUsers, deleteUser } from '../models/userModel';
|
import { createUser, loginUser, getAllUsers, deleteUser } from '../models/userModel';
|
||||||
import { ApiError } from '../utils/ApiError';
|
import { ApiError } from '../utils/ApiError';
|
||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
import { clearJwtCookie, setJwtCookie } from '../middlewares/checkAuth';
|
import { clearJwtCookie, setJwtCookie } from '../middlewares/checkAuth';
|
||||||
|
|
||||||
const create = async (req: Request, res: Response, next) => {
|
const create = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
try {
|
try {
|
||||||
const { email, password, address } = req.body;
|
const { email, password, address } = req.body;
|
||||||
const user = await createUser({
|
const user = await createUser({
|
||||||
|
@ -24,7 +24,7 @@ const create = async (req: Request, res: Response, next) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const login = async (req: Request, res: Response, next) => {
|
const login = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
try {
|
try {
|
||||||
const { email, password } = req.body;
|
const { email, password } = req.body;
|
||||||
const user: any = await loginUser({
|
const user: any = await loginUser({
|
||||||
|
@ -53,7 +53,7 @@ const login = async (req: Request, res: Response, next) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const logout = async (req: Request, res: Response, next) => {
|
const logout = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
try {
|
try {
|
||||||
clearJwtCookie(res);
|
clearJwtCookie(res);
|
||||||
res.status(200).json({ message: 'Logout successful' });
|
res.status(200).json({ message: 'Logout successful' });
|
||||||
|
@ -65,7 +65,7 @@ const logout = async (req: Request, res: Response, next) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getAll = async (req: Request, res: Response, next) => {
|
const getAll = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
try {
|
try {
|
||||||
const users = await getAllUsers();
|
const users = await getAllUsers();
|
||||||
res.status(200).json(users);
|
res.status(200).json(users);
|
||||||
|
@ -77,7 +77,7 @@ const getAll = async (req: Request, res: Response, next) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteHandler = async (req: Request, res: Response, next) => {
|
const deleteHandler = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
try {
|
try {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
const user = await deleteUser(id);
|
const user = await deleteUser(id);
|
||||||
|
|
|
@ -6,7 +6,6 @@ import userRouter from './routes/userRouter';
|
||||||
import productRouter from './routes/productRouter';
|
import productRouter from './routes/productRouter';
|
||||||
import cartRouter from './routes/cartRouter';
|
import cartRouter from './routes/cartRouter';
|
||||||
|
|
||||||
import { errorHandler } from './middlewares/errorHandler';
|
|
||||||
import { ApiError } from './utils/ApiError';
|
import { ApiError } from './utils/ApiError';
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,8 +46,6 @@ app.all('*', (req, res, next) => {
|
||||||
next(error)
|
next(error)
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use(errorHandler);
|
|
||||||
|
|
||||||
|
|
||||||
// Start server
|
// Start server
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
const errorHandler = (error, req, res, next) => {
|
|
||||||
error.statusCode = error.statusCode || 500;
|
|
||||||
error.message = error.message || 'Internal server error';
|
|
||||||
error.status = error.status || 'error';
|
|
||||||
res.status(error.statusCode).json({
|
|
||||||
status: error.status,
|
|
||||||
statusCode: error.statusCode,
|
|
||||||
message: error.message
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
|
||||||
errorHandler
|
|
||||||
}
|
|
14
src/middlewares/productResourceValidation.ts
Normal file
14
src/middlewares/productResourceValidation.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { Request, Response, NextFunction } from 'express';
|
||||||
|
import { ApiError } from '../utils/ApiError';
|
||||||
|
|
||||||
|
const isValidBody = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
const { name, description, price } = req.body;
|
||||||
|
if (!name || !description || !price) {
|
||||||
|
console.log("Error in product validation")
|
||||||
|
const error = new ApiError(`${!name ? 'name' : !description ? 'description' : 'price'} is required}`);
|
||||||
|
error.statusCode = 400;
|
||||||
|
error.status = 'fail';
|
||||||
|
return next(error);
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
41
src/middlewares/usersResourceValidation.ts
Normal file
41
src/middlewares/usersResourceValidation.ts
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import { Request, Response, NextFunction } from 'express';
|
||||||
|
import { ApiError } from '../utils/ApiError';
|
||||||
|
import validate from 'deep-email-validator';
|
||||||
|
|
||||||
|
const isValidLogin = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
|
||||||
|
const user = req.body;
|
||||||
|
if (!user.email || !user.password) {
|
||||||
|
const error = new ApiError(`${!user.email ? 'email' : 'password'} is required`);
|
||||||
|
error.statusCode = 400;
|
||||||
|
error.status = 'fail';
|
||||||
|
return next(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
const isValidCreateUser = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
|
||||||
|
const user = req.body;
|
||||||
|
if (!user.email || !user.password || !user.address) {
|
||||||
|
const error = new ApiError(`${!user.email ? 'email' : !user.password ? 'password' : 'address'} is required}`);
|
||||||
|
error.statusCode = 400;
|
||||||
|
error.status = 'fail';
|
||||||
|
return next(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { valid, reason } = await validate(user.email);
|
||||||
|
if (!valid) {
|
||||||
|
const error = new ApiError(`Invalid email: ${reason}`);
|
||||||
|
error.statusCode = 400;
|
||||||
|
error.status = 'fail';
|
||||||
|
return next(error);
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
isValidLogin,
|
||||||
|
isValidCreateUser
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
import { Product } from '../schemas/productSchema';
|
import { Product } from '../schemas/productSchema';
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { errorHandler } from '../middlewares/errorHandler';
|
|
||||||
import { ApiError } from '../utils/ApiError';
|
import { ApiError } from '../utils/ApiError';
|
||||||
|
|
||||||
const createProduct = async (product: any) => {
|
const createProduct = async (product: any) => {
|
||||||
|
@ -54,6 +53,19 @@ const getOne = async (id: string) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const removeProduct = async (id: string) => {
|
||||||
|
try {
|
||||||
|
const product = await Product.findByIdAndDelete(id);
|
||||||
|
return product;
|
||||||
|
} catch {
|
||||||
|
const error = new ApiError('Product not found');
|
||||||
|
error.statusCode = 404;
|
||||||
|
error.status = 'fail';
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
createProduct,
|
createProduct,
|
||||||
|
|
|
@ -1,25 +1,9 @@
|
||||||
import { User } from "../schemas/userSchema";
|
import { User } from "../schemas/userSchema";
|
||||||
import validate from 'deep-email-validator';
|
|
||||||
import { ApiError } from "../utils/ApiError";
|
import { ApiError } from "../utils/ApiError";
|
||||||
import bcrypt from 'bcryptjs';
|
import bcrypt from 'bcryptjs';
|
||||||
|
|
||||||
const createUser = async (user: any) => {
|
const createUser = async (user: any) => {
|
||||||
|
|
||||||
if (!user.email || !user.password || !user.address) {
|
|
||||||
const error = new ApiError('Missing required fields');
|
|
||||||
error.statusCode = 400;
|
|
||||||
error.status = 'fail';
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { valid, reason, validators } = await validate(user.email);
|
|
||||||
if (!valid) {
|
|
||||||
const error = new ApiError(reason);
|
|
||||||
error.statusCode = 400;
|
|
||||||
error.status = 'fail';
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
const userExists = await User.exists({ email: user.email });
|
const userExists = await User.exists({ email: user.email });
|
||||||
if (userExists) {
|
if (userExists) {
|
||||||
const error = new ApiError('User already exists, Try login :)');
|
const error = new ApiError('User already exists, Try login :)');
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { authenticateToken } from '../middlewares/checkAuth';
|
import { authenticateToken } from '../middlewares/checkAuth';
|
||||||
import { create, getAll, getProduct } from '../controllers/productController';
|
import { create, getAll, getProduct } from '../controllers/ProductController';
|
||||||
|
|
||||||
const productRouter = express.Router();
|
const productRouter = express.Router();
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { create, login, logout, getAll, deleteHandler } from '../controllers/userController';
|
import { create, login, logout, getAll, deleteHandler } from '../controllers/UserController';
|
||||||
|
import { isValidCreateUser, isValidLogin } from '../middlewares/usersResourceValidation';
|
||||||
|
import { authenticateToken } from '../middlewares/checkAuth';
|
||||||
|
|
||||||
const userRouter = express.Router();
|
const userRouter = express.Router();
|
||||||
|
|
||||||
userRouter.post('/', create);
|
userRouter.post('/', isValidCreateUser, create);
|
||||||
userRouter.get('/', getAll);
|
userRouter.get('/', getAll);
|
||||||
userRouter.post('/login', login);
|
userRouter.post('/login', isValidLogin, login);
|
||||||
userRouter.post('/logout', logout);
|
userRouter.post('/logout', logout);
|
||||||
userRouter.delete('/:id', deleteHandler)
|
userRouter.delete('/:id', authenticateToken, deleteHandler)
|
||||||
|
|
||||||
export default userRouter;
|
export default userRouter;
|
|
@ -1,5 +1,4 @@
|
||||||
import mongoose, { Schema, Document } from 'mongoose';
|
import mongoose, { Schema, Document } from 'mongoose';
|
||||||
import { Request } from 'express';
|
|
||||||
|
|
||||||
interface IProduct extends Document {
|
interface IProduct extends Document {
|
||||||
name: string;
|
name: string;
|
||||||
|
|
|
@ -9,5 +9,6 @@
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
"rootDir": "./src",
|
"rootDir": "./src",
|
||||||
|
"noImplicitAny": true,
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue