-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(product managment) add product managment this commit adds produc…
…t entity with its relation of a vendor. it is used to implement product managment for vendor. Resolves: #48
- Loading branch information
Showing
26 changed files
with
537 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { Request, Response } from 'express'; | ||
import { createProductService, updateProductService, removeProductImageService, readProductService, readProductsService, deleteProductService } from '../services'; | ||
|
||
export const readProduct = async (req: Request, res: Response) => { | ||
await readProductService(req, res); | ||
}; | ||
|
||
export const readProducts = async (req: Request, res: Response) => { | ||
await readProductsService(req, res); | ||
}; | ||
|
||
export const createProduct = async (req: Request, res: Response) => { | ||
await createProductService(req, res); | ||
}; | ||
|
||
export const updateProduct = async (req: Request, res: Response) => { | ||
await updateProductService(req, res); | ||
}; | ||
|
||
export const removeProductImage = async (req: Request, res: Response) => { | ||
await removeProductImageService(req, res); | ||
}; | ||
|
||
export const deleteProduct = async (req: Request, res: Response) => { | ||
await deleteProductService(req, res); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { Entity, PrimaryGeneratedColumn, Column, Unique, ManyToOne, CreateDateColumn, UpdateDateColumn } from 'typeorm'; | ||
import { IsNotEmpty, IsString, IsBoolean, ArrayNotEmpty, IsArray, MaxLength } from 'class-validator'; | ||
import { User } from './User'; | ||
|
||
@Entity() | ||
@Unique(['id']) | ||
export class Product { | ||
@PrimaryGeneratedColumn('uuid') | ||
@IsNotEmpty() | ||
id!: string; | ||
|
||
@ManyToOne(() => User) | ||
@IsNotEmpty() | ||
vendor!: User; | ||
|
||
@Column() | ||
@IsNotEmpty() | ||
@IsString() | ||
name!: string; | ||
|
||
@Column() | ||
@IsNotEmpty() | ||
description!: string; | ||
|
||
@Column('simple-array') | ||
@IsArray() | ||
@ArrayNotEmpty() | ||
@MaxLength(10) | ||
images!: string[]; | ||
|
||
@Column('decimal') | ||
@IsNotEmpty() | ||
newPrice!: number; | ||
|
||
@Column('decimal', { nullable: true }) | ||
oldPrice?: number; | ||
|
||
@Column('timestamp', { nullable: true }) | ||
expirationDate?: Date; | ||
|
||
@Column('int') | ||
@IsNotEmpty() | ||
quantity!: number; | ||
|
||
@Column({ default: true }) | ||
@IsBoolean() | ||
isAvailable!: boolean; | ||
|
||
@CreateDateColumn() | ||
createdAt!: Date; | ||
|
||
@UpdateDateColumn() | ||
updatedAt!: Date; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import Joi from 'joi'; | ||
import { Product } from '../lib/types'; | ||
|
||
export const validateProduct = ( | ||
product: Pick<Product, 'name' | 'description' | 'newPrice' | 'quantity' | 'expirationDate'> | ||
): Joi.ValidationResult<any> => { | ||
const schema = Joi.object({ | ||
name: Joi.string().min(3).required().messages({ | ||
'any.required': 'name is required.', | ||
}), | ||
description: Joi.string().min(3).required().messages({ | ||
'any.required': 'description is required.', | ||
}), | ||
newPrice: Joi.number().required().messages({ | ||
'any.required': 'newPrice is required.', | ||
}), | ||
quantity: Joi.number().required().messages({ | ||
'any.required': 'quantity is required.', | ||
}), | ||
expirationDate: Joi.date(), | ||
oldPrice: Joi.number(), | ||
}); | ||
|
||
return schema.validate(product); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { User } from '../entities/User'; | ||
|
||
export type Product = { | ||
id: string; | ||
vendor: User; | ||
name: string; | ||
description: string; | ||
images: string[]; | ||
newPrice: number; | ||
oldPrice?: number; | ||
expirationDate?: Date; | ||
quantity: number; | ||
isAvailable: boolean; | ||
createdAt: Date; | ||
updatedAt: Date; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import multer from 'multer'; | ||
import path from 'path'; | ||
|
||
export default multer({ | ||
storage: multer.diskStorage({}), | ||
fileFilter: (req, file, next) => { | ||
const ext = path.extname(file.originalname); | ||
const supported = ['.png', '.jpg', '.jpeg', '.webp']; | ||
if (!supported.includes(ext)) { | ||
next(new Error(`file type not supported\ntry ${supported} are supported`)); | ||
} | ||
next(null, true); | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { Request, Response, NextFunction } from 'express'; | ||
import { User, UserInterface } from '../entities/User'; | ||
import { getRepository } from 'typeorm'; | ||
import jwt, { type JwtPayload, type Secret } from 'jsonwebtoken'; | ||
import dotenv from 'dotenv'; | ||
|
||
dotenv.config(); | ||
|
||
interface AuthRequest extends Request { | ||
user?: UserInterface; | ||
} | ||
|
||
export const authMiddleware = async (req: AuthRequest, res: Response, next: NextFunction) => { | ||
const authHeader = req.headers.authorization; | ||
|
||
if (authHeader === undefined) { | ||
return res.status(401).json({ error: 'Access denied. No token provided.' }); | ||
} | ||
|
||
const [bearer, token] = authHeader.split(' '); | ||
|
||
if (bearer !== 'Bearer' || token === undefined) { | ||
return res.status(401).json({ error: 'Please login' }); | ||
} | ||
|
||
if (token !== undefined) { | ||
try { | ||
jwt.verify(token, process.env.JWT_SECRET as Secret, async (err, decodedToken) => { | ||
if (err !== null) { | ||
return res.status(403).json({ status: 'error', error: 'Access denied' }); | ||
} | ||
|
||
if (decodedToken !== undefined) { | ||
const { email } = decodedToken as JwtPayload; | ||
const userRepository = getRepository(User); | ||
const user = await userRepository.findOneBy({ email }); | ||
|
||
if (!user) { | ||
return res.status(401).json({ status: 'error', error: 'You are not Authorized' }); | ||
} | ||
|
||
req.user = user as UserInterface; | ||
next(); | ||
} | ||
}); | ||
} catch (error) { | ||
return res.status(401).json({ error: 'Invalid token' }); | ||
} | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { Router } from 'express'; | ||
|
||
import upload from '../middlewares/multer'; | ||
import { authMiddleware } from '../middlewares/verifyToken'; | ||
import { hasRole } from '../middlewares'; | ||
import { createProduct, updateProduct, removeProductImage, readProducts, readProduct, deleteProduct } from '../controllers/productController'; | ||
|
||
const router = Router(); | ||
|
||
router.get('/', authMiddleware, hasRole('VENDOR'), readProducts); | ||
router.get('/:id', authMiddleware, hasRole('VENDOR'), readProduct); | ||
router.post('/', authMiddleware, hasRole('VENDOR'), upload.array('images', 10), createProduct); | ||
router.put('/:id', authMiddleware, hasRole('VENDOR'), upload.array('images', 10), updateProduct); | ||
router.delete('/images/:id', authMiddleware, hasRole('VENDOR'), removeProductImage); | ||
router.delete('/:id', authMiddleware, hasRole('VENDOR'), deleteProduct); | ||
|
||
export default router; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,17 @@ | ||
|
||
export * from "./userServices/sendResetPasswordLinkService"; | ||
export * from "./userServices/userPasswordResetService"; | ||
export * from "./userServices/userRegistrationService"; | ||
export * from "./userServices/userValidationService"; | ||
export * from './userServices/sendResetPasswordLinkService'; | ||
export * from './userServices/userPasswordResetService'; | ||
export * from './userServices/userRegistrationService'; | ||
export * from './userServices/userValidationService'; | ||
export * from './userServices/userEnableTwoFactorAuth'; | ||
export * from './userServices/userDisableTwoFactorAuth'; | ||
export * from './userServices/userValidateOTP'; | ||
export * from './userServices/userLoginService'; | ||
export * from './userServices/userResendOTP'; | ||
export * from './userServices/logoutServices'; | ||
|
||
// Vendor product services | ||
export * from './productServices/createProduct'; | ||
export * from './productServices/updateProduct'; | ||
export * from './productServices/removeProductImage'; | ||
export * from './productServices/readProduct'; | ||
export * from './productServices/deleteProduct'; |
Oops, something went wrong.