diff --git a/src/controllers/auth.controller.ts b/src/controllers/auth.controller.ts index e69de29..e5b4734 100644 --- a/src/controllers/auth.controller.ts +++ b/src/controllers/auth.controller.ts @@ -0,0 +1,28 @@ +import { Request, Response, NextFunction } from "express"; +import { AuthService } from "../services/auth.service"; + +export class AuthController { + static async register(req: Request, res: Response, next: NextFunction) { + try { + const { email, password } = req.body; + + const user = await AuthService.register(email, password); + + res.status(201).json(user); + } catch (err) { + next(err); + } + } + + static async login(req: Request, res: Response, next: NextFunction) { + try { + const { email, password } = req.body; + + const result = await AuthService.login(email, password); + + res.status(200).json(result); + } catch (err) { + next(err); + } + } +} diff --git a/src/controllers/product.controller.ts b/src/controllers/product.controller.ts index e69de29..f9d21cf 100644 --- a/src/controllers/product.controller.ts +++ b/src/controllers/product.controller.ts @@ -0,0 +1,32 @@ +import { Request, Response, NextFunction } from "express"; +import { ProductService } from "../services/product.service"; + +export class ProductController { + static async create(req: Request, res: Response, next: NextFunction) { + try { + const product = await ProductService.create(req.body); + res.status(201).json(product); + } catch (err) { + next(err); + } + } + + static async list(_req: Request, res: Response, next: NextFunction) { + try { + const products = await ProductService.list(); + res.status(200).json(products); + } catch (err) { + next(err); + } + } + + static async update(req: Request, res: Response, next: NextFunction) { + try { + const { id } = req.params; + const product = await ProductService.update(id, req.body); + res.status(200).json(product); + } catch (err) { + next(err); + } + } +} diff --git a/src/services/auth.service.ts b/src/services/auth.service.ts index e69de29..adb2c2f 100644 --- a/src/services/auth.service.ts +++ b/src/services/auth.service.ts @@ -0,0 +1,47 @@ +import bcrypt from "bcrypt"; +import { UserModel } from "../models/user.model"; +import { signToken } from "../utils/jwt"; + +const SALT_ROUNDS = 10; + +export class AuthService { + static async register(email: string, password: string) { + const existing = await UserModel.findOne({ email }); + if (existing) { + throw { statusCode: 409, message: "Email already registered" }; + } + + const passwordHash = await bcrypt.hash(password, SALT_ROUNDS); + + const user = await UserModel.create({ + email, + passwordHash, + role: "customer", + }); + + return { + id: user._id, + email: user.email, + role: user.role, + }; + } + + static async login(email: string, password: string) { + const user = await UserModel.findOne({ email }); + if (!user) { + throw { statusCode: 401, message: "Invalid credentials" }; + } + + const valid = await bcrypt.compare(password, user.passwordHash); + if (!valid) { + throw { statusCode: 401, message: "Invalid credentials" }; + } + + const token = signToken({ + sub: user._id, + role: user.role, + }); + + return { token }; + } +} diff --git a/src/services/product.service.ts b/src/services/product.service.ts index e69de29..feef6ce 100644 --- a/src/services/product.service.ts +++ b/src/services/product.service.ts @@ -0,0 +1,29 @@ +import { ProductModel } from "../models/product.model"; + +export class ProductService { + static async create(data: { name: string; price: number; stock: number }) { + const product = await ProductModel.create(data); + return product; + } + + static async list() { + return ProductModel.find().lean(); + } + + static async update( + id: string, + data: Partial<{ name: string; price: number; stock: number }>, + ) { + const product = await ProductModel.findByIdAndUpdate( + id, + { $set: data }, + { new: true }, + ); + + if (!product) { + throw { statusCode: 404, message: "Product not found" }; + } + + return product; + } +} diff --git a/src/validation/auth.schema.ts b/src/validation/auth.schema.ts index e69de29..433bdee 100644 --- a/src/validation/auth.schema.ts +++ b/src/validation/auth.schema.ts @@ -0,0 +1,15 @@ +import { z } from "zod"; + +export const registerSchema = z.object({ + body: z.object({ + email: z.string().email(), + password: z.string().min(8), + }), +}); + +export const loginSchema = z.object({ + body: z.object({ + email: z.string().email(), + password: z.string().min(1), + }), +}); diff --git a/src/validation/order.schema.ts b/src/validation/order.schema.ts index e69de29..d4078f9 100644 --- a/src/validation/order.schema.ts +++ b/src/validation/order.schema.ts @@ -0,0 +1,20 @@ +import { z } from "zod"; + +export const createOrderSchema = z.object({ + body: z.object({ + items: z + .array( + z.object({ + productId: z.string().uuid(), + quantity: z.number().int().positive(), + }), + ) + .min(1), + }), +}); + +export const orderIdParamSchema = z.object({ + params: z.object({ + id: z.string().uuid(), + }), +});