Skip to content

Commit

Permalink
Update: Added nodemon and SwaggerJS
Browse files Browse the repository at this point in the history
  • Loading branch information
hoangsonww committed Oct 21, 2024
1 parent 07472a8 commit 015ed7d
Show file tree
Hide file tree
Showing 19 changed files with 1,549 additions and 47 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,20 @@ Please note that the backend server may take a few seconds to wake up if it has
- Material-UI for styling
- Axios for API requests
- `react-credit-cards-2` for credit card visualization
- `react-router-dom` for routing
- `react-hook-form` for form validation
- `react-toastify` for toast notifications
- Jest and React Testing Library for testing

- **Backend:**
- Node.js
- Express.js
- MongoDB (with Mongoose ODM)
- Axios for external API requests
- JsonWebToken for user authentication
- Bcrypt for password hashing
- Dotenv for environment variables
- Cors for cross-origin resource sharing
- Swagger for API documentation
- Nodemon for server hot-reloading

Expand Down
128 changes: 123 additions & 5 deletions backend/docs/swagger.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,144 @@ const swaggerUi = require('swagger-ui-express');
const swaggerDefinition = {
openapi: '3.0.0',
info: {
title: 'Fusion E-Commerce Backend APIs',
version: '1.0.0',
description: 'API documentation for the Fusion E-Commerce backend server.',
title: 'Fusion E-Commerce Backend APIs', // API title
version: '1.1.0', // API version
description: 'API documentation for the Fusion E-Commerce backend server. This documentation provides detailed information on all available endpoints for managing products, users, authentication, and more.',
termsOfService: 'https://mern-stack-ecommerce-app-nine.vercel.app',
contact: {
name: 'Fusion E-Commerce Website',
url: 'https://mern-stack-ecommerce-app-nine.vercel.app',
email: '[email protected]', // Contact email
},
license: {
name: 'MIT License',
url: 'https://opensource.org/licenses/MIT', // License link
},
},
servers: [
{
url: 'https://mern-stack-ecommerce-app-h5wb.onrender.com',
description: 'Production server',
},
{
url: 'http://localhost:5000',
url: 'http://localhost:8000',
description: 'Development server',
}
],
components: {
securitySchemes: {
BearerAuth: {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
},
},
schemas: {
Product: {
type: 'object',
required: ['name', 'price', 'description', 'category'],
properties: {
id: {
type: 'string',
description: 'Product ID',
},
name: {
type: 'string',
description: 'Name of the product',
},
description: {
type: 'string',
description: 'Detailed description of the product',
},
price: {
type: 'number',
description: 'Price of the product in USD',
},
category: {
type: 'string',
description: 'Category the product belongs to',
},
brand: {
type: 'string',
description: 'Brand of the product',
},
stock: {
type: 'integer',
description: 'Stock count available',
},
rating: {
type: 'number',
description: 'Average rating of the product',
},
numReviews: {
type: 'integer',
description: 'Number of reviews for the product',
},
image: {
type: 'string',
description: 'URL of the product image',
},
},
example: {
id: '507f1f77bcf86cd799439011',
name: 'Wireless Headphones',
description: 'Noise-cancelling wireless headphones with long battery life.',
price: 99.99,
category: 'Electronics',
brand: 'Fusion',
stock: 150,
rating: 4.7,
numReviews: 89,
image: 'https://example.com/product.jpg',
},
},
User: {
type: 'object',
required: ['name', 'email', 'password'],
properties: {
id: {
type: 'string',
description: 'User ID',
},
name: {
type: 'string',
description: 'Full name of the user',
},
email: {
type: 'string',
description: 'Email address of the user',
},
password: {
type: 'string',
description: 'Password for the user account',
},
createdAt: {
type: 'string',
format: 'date-time',
description: 'Account creation date',
},
},
example: {
id: '507f1f77bcf86cd799439011',
name: 'John Doe',
email: '[email protected]',
password: 'password123',
createdAt: '2023-10-21T14:21:00Z',
},
},
},
},
security: [
{
BearerAuth: [],
},
],
};

// Options for the swagger docs
const options = {
swaggerDefinition,
apis: ['./routes/*.js'],
apis: ['./routes/*.js'], // Specify the path to API files with JSDoc comments
};

// Initialize swagger-jsdoc
Expand Down
8 changes: 5 additions & 3 deletions backend/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
const dotenv = require('dotenv');
dotenv.config();

const express = require('express');
const cors = require('cors');
const mongoose = require('mongoose');
const dotenv = require('dotenv');
const seedDB = require('./seed/productSeeds');
const productRoutes = require('./routes/products');
const checkoutRoutes = require('./routes/checkout');
const authRoutes = require('./routes/auth');
const { swaggerUi, swaggerSpec } = require('./docs/swagger');

dotenv.config();

// Create Express App
const app = express();
const PORT = process.env.PORT || 8000;
Expand All @@ -33,6 +34,7 @@ app.get('/', (req, res) => {
app.use('/api/products', productRoutes);
app.use('/api/checkout', checkoutRoutes);
app.use('/api/search', require('./routes/search'));
app.use('/api/auth', authRoutes);
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));

// Seed database on startup
Expand Down
26 changes: 26 additions & 0 deletions backend/middleware/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const jwt = require('jsonwebtoken');
const JWT_SECRET = process.env.JWT_SECRET;

// Authentication middleware for protected routes
module.exports = function (req, res, next) {
// Get token from the header
const token = req.header('x-auth-token');

// Check if there's no token
if (!token) {
return res.status(401).json({ msg: 'No token, authorization denied' });
}

try {
// Verify the token
const decoded = jwt.verify(token, JWT_SECRET);

// Attach the user payload to the request object
req.user = decoded.user;

// Call next middleware
next();
} catch (err) {
res.status(401).json({ msg: 'Token is not valid' });
}
};
23 changes: 23 additions & 0 deletions backend/models/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const mongoose = require('mongoose');

const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
});

module.exports = mongoose.model('User', UserSchema);
32 changes: 32 additions & 0 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"express-validator": "^7.2.0",
"mongoose": "^8.4.3",
"swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.1"
Expand Down
Loading

0 comments on commit 015ed7d

Please sign in to comment.