S50 Capstone added
parent
acfadce5cb
commit
4b003da8da
@ -0,0 +1 @@
|
|||||||
|
web: node index.js
|
@ -1,40 +1,53 @@
|
|||||||
const jwt = require('jsonwebtoken');
|
// middlewares/auth.js
|
||||||
require("dotenv").config()
|
|
||||||
|
|
||||||
// Function to verify JWT token
|
const jwt = require("jsonwebtoken")
|
||||||
exports.verifyToken = (token) => {
|
require("dotenv").config()
|
||||||
try {
|
|
||||||
const decoded = jwt.verify(token, process.env.SECRET_SAUCE);
|
|
||||||
return decoded;
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return null; // Return null if verification fails
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Middleware for verifying JWT token
|
// Middleware for verifying and authenticating JWT token
|
||||||
exports.authenticateToken = (req, res, next) => {
|
exports.authenticateToken = (req, res, next) => {
|
||||||
// Extract the token from the Authorization header
|
// Extract the token from the Authorization header
|
||||||
const token = req.header('Authorization')?.replace('Bearer ', '');
|
const token = req.header("Authorization")?.replace("Bearer ", "")
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return res.status(401).json({ message: 'Unauthorized. Token not provided.' });
|
return res
|
||||||
|
.status(401)
|
||||||
|
.json({ message: "Unauthorized. Token not provided." })
|
||||||
}
|
}
|
||||||
|
|
||||||
const decoded = exports.verifyToken(token);
|
console.log("Token:", token) // Log the token to the console
|
||||||
|
|
||||||
if (!decoded) {
|
try {
|
||||||
return res.status(401).json({ message: 'Unauthorized. Invalid token.' });
|
const decoded = jwt.verify(token, process.env.SECRET_SAUCE)
|
||||||
}
|
req.user = decoded // Attach the decoded information to the request for future use
|
||||||
|
|
||||||
// Attach the decoded information to the request for future use
|
// dEBUGGING PURPOSES
|
||||||
req.user = decoded;
|
console.log("userId:", decoded.userId)
|
||||||
|
console.log("isAdmin:", decoded.isAdmin)
|
||||||
|
|
||||||
// Proceed to the next middleware or route handler
|
next()
|
||||||
next();
|
} catch (error) {
|
||||||
};
|
console.error("Token Verification Error:", error)
|
||||||
|
return res
|
||||||
|
.status(401)
|
||||||
|
.json({ message: "Unauthorized. Invalid or expired token." })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Function to generate a JWT token
|
// Function to generate a JWT token
|
||||||
exports.generateToken = (userId, email) => {
|
exports.generateToken = (userId, email, isAdmin) => {
|
||||||
return jwt.sign({ userId, email }, process.env.SECRET_SAUCE, { expiresIn: '1h' });
|
return jwt.sign({ userId, email, isAdmin }, process.env.SECRET_SAUCE, {
|
||||||
};
|
expiresIn: "1h",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Middleware to verify admin status
|
||||||
|
exports.verifyAdmin = (req, res, next) => {
|
||||||
|
if (req.user && req.user.isAdmin) {
|
||||||
|
next()
|
||||||
|
} else {
|
||||||
|
return res
|
||||||
|
.status(403)
|
||||||
|
.json({ message: "Action Forbidden. User is not an admin." })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
const User = require("../model/User")
|
||||||
|
|
||||||
|
exports.createOrder = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { userId, products, totalAmount } = req.body
|
||||||
|
|
||||||
|
const user = await User.findById(userId)
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(404).json({ message: "User not found" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const newOrder = {
|
||||||
|
products: products,
|
||||||
|
totalAmount: totalAmount,
|
||||||
|
purchaseOn: Date.now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
user.orderedProducts.push(newOrder)
|
||||||
|
await user.save()
|
||||||
|
|
||||||
|
res.status(201).json({
|
||||||
|
message: "Order created successfully",
|
||||||
|
order: newOrder,
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
res.status(500).json({ message: "Internal Server Error" })
|
||||||
|
}
|
||||||
|
}
|
@ -1,52 +1,141 @@
|
|||||||
// productController.js
|
const Product = require("../model/Product")
|
||||||
const Product = require('../model/Product');
|
|
||||||
|
|
||||||
// Controller function for creating a product (accessible only by isAdmin)
|
|
||||||
exports.createProduct = async (req, res) => {
|
exports.createProduct = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
// Check if the user is an admin
|
const { name, description, price } = req.body
|
||||||
if (!req.user.isAdmin) {
|
|
||||||
return res.status(403).json({ message: 'Permission denied. Only admins can create products.' });
|
const newProduct = new Product({ name, description, price })
|
||||||
|
await newProduct.save()
|
||||||
|
res.status(201).json(newProduct)
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: error.message })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controller function for retrieving all products (accessible to both admin and normal user)
|
||||||
|
exports.getAllProducts = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const products = await Product.find()
|
||||||
|
|
||||||
|
res.status(200).json(products)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
res.status(500).json({ message: "Internal server error" })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controller function for retrieving all active products (accessible to both admin and normal user)
|
||||||
|
exports.getActiveProducts = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const activeProducts = await Product.find({ isActive: true })
|
||||||
|
|
||||||
|
res.status(200).json(activeProducts)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
res.status(500).json({ message: "Internal server error" })
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controller to retrieve a single product by id
|
||||||
|
exports.getProductById = async (req, res) => {
|
||||||
|
const productId = req.params.id;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const product = await Product.findById(productId);
|
||||||
|
|
||||||
|
if (!product) {
|
||||||
|
return res.status(404).json({ message: 'Product not found' });
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json(product);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: 'Internal server error' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Controller function to update product information
|
||||||
|
exports.updateProduct = async (req, res) => {
|
||||||
|
const productId = req.params.id;
|
||||||
const { name, description, price, isActive } = req.body;
|
const { name, description, price, isActive } = req.body;
|
||||||
|
|
||||||
const newProduct = new Product({
|
try {
|
||||||
name,
|
// Check if the product exists
|
||||||
description,
|
const existingProduct = await Product.findById(productId);
|
||||||
price,
|
if (!existingProduct) {
|
||||||
isActive,
|
return res.status(404).json({ message: 'Product not found' });
|
||||||
});
|
}
|
||||||
|
|
||||||
|
// Update product information
|
||||||
|
existingProduct.name = name;
|
||||||
|
existingProduct.description = description;
|
||||||
|
existingProduct.price = price;
|
||||||
|
existingProduct.isActive = isActive;
|
||||||
|
|
||||||
await newProduct.save();
|
// Save the updated product
|
||||||
|
const updatedProduct = await existingProduct.save();
|
||||||
|
|
||||||
res.status(201).json({ message: 'Product created successfully' });
|
res.status(200).json(updatedProduct);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
res.status(500).json({ message: 'Internal server error' });
|
res.status(500).json({ message: 'Internal Server Error' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Controller function for retrieving all products (accessible to both admin and normal user)
|
exports.activateProduct = async (req, res) => {
|
||||||
exports.getAllProducts = async (req, res) => {
|
const { productId } = req.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const products = await Product.find();
|
// Find the product by ID
|
||||||
|
const product = await Product.findById(productId);
|
||||||
|
|
||||||
|
if (!product) {
|
||||||
|
return res.status(404).json({ message: 'Product not found' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the product is already active
|
||||||
|
if (product.isActive) {
|
||||||
|
return res.status(400).json({ message: 'Product is already active' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activate the product
|
||||||
|
product.isActive = true;
|
||||||
|
|
||||||
res.status(200).json(products);
|
// Save the updated product
|
||||||
|
await product.save();
|
||||||
|
|
||||||
|
res.json({ message: 'Product activated successfully', product });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
res.status(500).json({ message: 'Internal server error' });
|
res.status(500).json({ message: 'Internal Server Error' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Controller function for retrieving all active products (accessible to both admin and normal user)
|
exports.archiveProduct = async (req, res) => {
|
||||||
exports.getActiveProducts = async (req, res) => {
|
const { productId } = req.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const activeProducts = await Product.find({ isActive: true });
|
// Find the product by ID
|
||||||
|
const product = await Product.findById(productId);
|
||||||
|
|
||||||
|
if (!product) {
|
||||||
|
return res.status(404).json({ message: 'Product not found' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the product is already active
|
||||||
|
if (!product.isActive) {
|
||||||
|
return res.status(400).json({ message: 'Product is already in Archive' });
|
||||||
|
}
|
||||||
|
|
||||||
res.status(200).json(activeProducts);
|
// Activate the product
|
||||||
|
product.isActive = false;
|
||||||
|
|
||||||
|
// Save the updated product
|
||||||
|
await product.save();
|
||||||
|
|
||||||
|
res.json({ message: 'Product successfuly archived', product });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
res.status(500).json({ message: 'Internal server error' });
|
res.status(500).json({ message: 'Internal Server Error' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,89 @@
|
|||||||
|
**** Accounts ****
|
||||||
|
|
||||||
|
User: ( Password: wapatu )
|
||||||
|
{
|
||||||
|
"userId": "65544d9be5c01f6c0ca79200",
|
||||||
|
"email": "wapatu@example.com",
|
||||||
|
"firstName": "Estevan",
|
||||||
|
"lastName": "Cummings",
|
||||||
|
"isAdmin": false,
|
||||||
|
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2NTU0NGQ5YmU1YzAxZjZjMGNhNzkyMDAiLCJlbWFpbCI6IndhcGF0dUBleGFtcGxlLmNvbSIsImlzQWRtaW4iOmZhbHNlLCJpYXQiOjE3MDAwMjM3MjQsImV4cCI6MTcwMDAyNzMyNH0.dpWV9Zx64TH4RLgmV_RlyrMBCa0HwDe9wJRAkwAyjys"
|
||||||
|
}
|
||||||
|
|
||||||
|
Admin: (Password is: admin )
|
||||||
|
{
|
||||||
|
"userId": "65535cb526b586a3e2fd56cc",
|
||||||
|
"email": "admin@email.com",
|
||||||
|
"isAdmin": true,
|
||||||
|
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2NTUzNWNiNTI2YjU4NmEzZTJmZDU2Y2MiLCJlbWFpbCI6ImFkbWluQGVtYWlsLmNvbSIsImlzQWRtaW4iOnRydWUsImlhdCI6MTcwMDAyMzgxMSwiZXhwIjoxNzAwMDI3NDExfQ.DrhpNlBJKpfHod7MfTalQ5j2-s8tnR630yh2-_EIYWw"
|
||||||
|
}
|
||||||
|
|
||||||
|
**** Links ****
|
||||||
|
|
||||||
|
REGISTER
|
||||||
|
http://localhost:3000/user/register
|
||||||
|
--> Use post
|
||||||
|
{
|
||||||
|
"email": "admin@email.com",
|
||||||
|
"password": "admin"
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGIN
|
||||||
|
http://localhost:3000/user/login
|
||||||
|
--> Use post
|
||||||
|
{
|
||||||
|
"email": "admin@email.com",
|
||||||
|
"password": "admin"
|
||||||
|
}
|
||||||
|
|
||||||
|
UPDATE PROFILE
|
||||||
|
http://localhost:3000/user/update
|
||||||
|
--> Must use Admin token // use put
|
||||||
|
{
|
||||||
|
"userId": "6554473388d9942bbf4de065",
|
||||||
|
"newEmail": "mundo@email.com",
|
||||||
|
"newFirstname": "Ron",
|
||||||
|
"newLastName": "Pogi",
|
||||||
|
"newPassword": "mundo"
|
||||||
|
}
|
||||||
|
|
||||||
|
CREATE PRODUCT [ADMIN]
|
||||||
|
http://localhost:3000/user/products
|
||||||
|
--> Must use Admin token // use post
|
||||||
|
{
|
||||||
|
"name": "Poring Card",
|
||||||
|
"description": "Description unknown",
|
||||||
|
"price": 500
|
||||||
|
}
|
||||||
|
|
||||||
|
GET ALL PRODUCT
|
||||||
|
http://localhost:3000/user/all
|
||||||
|
--> Use get
|
||||||
|
|
||||||
|
GET ALL ACTIVE PRODUCT
|
||||||
|
http://localhost:3000/user/active
|
||||||
|
--> Use get
|
||||||
|
|
||||||
|
GET A SINGLE PROUCT
|
||||||
|
http://localhost:3000/user/products/65538bd4a601aa30730f6d4c
|
||||||
|
--> Use get
|
||||||
|
|
||||||
|
UPDATE A PRODUCT [ADMIN]
|
||||||
|
http://localhost:3000/user/products/65545a1e6fa9d841e1518d1d
|
||||||
|
--> Must use Admin token // Use put
|
||||||
|
{
|
||||||
|
"name": "Christmas Cookie Card",
|
||||||
|
"description": "Updated Product Description",
|
||||||
|
"price": 29.99,
|
||||||
|
"isActive": false
|
||||||
|
}
|
||||||
|
|
||||||
|
ACTIVATE / ARCHIVE A PRODUCT [ADMIN]
|
||||||
|
--> Use Put
|
||||||
|
http://localhost:3000/user/products/6554634e5cac4bcd6f2394ed/activate
|
||||||
|
http://localhost:3000/user/products/6554634e5cac4bcd6f2394ed/archive
|
||||||
|
|
||||||
|
|
||||||
|
RETRIEVE OWN USER DATA
|
||||||
|
--> Use Get
|
||||||
|
http://localhost:3000/user/65535cb526b586a3e2fd56cc
|
@ -1,18 +1,32 @@
|
|||||||
const express = require('express');
|
const express = require("express")
|
||||||
const router = express.Router();
|
const router = express.Router()
|
||||||
const productController = require('../controllers/product');
|
const productController = require("../controllers/product")
|
||||||
const auth = require('./auth'); // Assuming you have an auth.js file with authentication middleware
|
const auth = require("../auth")
|
||||||
|
|
||||||
// Middleware for authorization token
|
const { authenticateToken, verifyAdmin } = auth
|
||||||
const authenticateToken = auth.authenticateToken;
|
|
||||||
|
|
||||||
|
// S50
|
||||||
// Create a product route (accessible only by isAdmin)
|
// Create a product route (accessible only by isAdmin)
|
||||||
router.post('/create', authenticateToken, productController.createProduct);
|
router.post("/products", authenticateToken, verifyAdmin, productController.createProduct)
|
||||||
|
|
||||||
// Retrieve all products route (accessible to both admin and normal user)
|
// Retrieve all products route (accessible to both admin and normal user)
|
||||||
router.get('/all', productController.getAllProducts);
|
router.get("/all", productController.getAllProducts)
|
||||||
|
|
||||||
// Retrieve all active products route (accessible to both admin and normal user)
|
// Retrieve all active products route (accessible to both admin and normal user)
|
||||||
router.get('/active', productController.getActiveProducts);
|
router.get("/active", productController.getActiveProducts)
|
||||||
|
|
||||||
module.exports = router;
|
// S51
|
||||||
|
// Retrieve a single product by ID
|
||||||
|
router.get('/products/:id', productController.getProductById);
|
||||||
|
|
||||||
|
// Update product route + admin verification
|
||||||
|
router.put('/products/:id', authenticateToken, verifyAdmin, productController.updateProduct);
|
||||||
|
|
||||||
|
// Archive a product
|
||||||
|
router.put('/products/:productId/archive', authenticateToken, verifyAdmin, productController.archiveProduct);
|
||||||
|
|
||||||
|
// Activate a product
|
||||||
|
router.put('/products/:productId/activate', authenticateToken, verifyAdmin, productController.activateProduct);
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = router
|
||||||
|
Loading…
Reference in New Issue