Version: 1.0.0
Author: Syed Tasavour
License: ISC
- Postman Collection: Postman Collection
- Flowchart Flowchart
- API Base URL: http://localhost:3000/api/v1/
- GitHub Repository: Syed Tasavour
If you found this project helpful, give it a ⭐️!
- Introduction
- System Architecture
- Setup & Installation
- API Features & Endpoints
- Authentication System
- Database Design
- File Upload System
- Deployment Guide (AWS)
- Security Measures
- Testing Guide
- Monitoring & Logging
- Troubleshooting
- Administrative Setup Guide
TechTales is a professional blogging platform API built with:
- Node.js & Express.js for the backend
- MongoDB for the database
- JWT for authentication
- Cloudinary for media storage
- AWS for deployment
Key Features:
- Multi-user blogging platform
- Role-based access control
- Media management
- Comment system
- Like/Unlike functionality
- Search capabilities
- Admin dashboard
Application Layers:
- Presentation Layer:
- REST API endpoints
- Request/Response handling
- Input validation
- Business Layer:
- Controllers
- Services
- Middleware
- Data Layer:
- MongoDB models
- Data access logic
- Caching (future implementation)
- External Services:
- Cloudinary (media storage)
- JWT (authentication)
- AWS (hosting)
Local Development Setup:
# Required software
Node.js >= 14.x
MongoDB >= 4.x
Git
# Clone repository
git clone https://github.com/syedtasavour/TechTales.git
cd TechTales
# Install dependencies
npm install
# Create environment file
cp .env.sample .env
# Server Configuration
PORT=3000
NODE_ENV=development
# Database
MONGODB_URI=mongodb://localhost:27017/techtales
# Authentication
ACESS_TOKEN_SECRET=your_secure_token_here
REFRESH_TOKEN_SECRET=your_secure_refresh_token
ACESS_TOKEN_EXPIRY=1d
REFRESH_TOKEN_EXPIRY=10d
# Cloudinary
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_API_SECRET=your_api_secret
# CORS
CORS_ORIGIN=http://localhost:3000
# Run with nodemon
npm run dev
# Run production
npm start
- User Registration
POST/api/v1/users/register
{
"fullName": "User Name",
"username": "unique_username",
"email": "[email protected]",
"password": "secure_password",
"avatar": "file_upload"
}
- User Login
POST/api/v1/users/login
{
"email": "[email protected]",
"password": "secure_password"
}
- Create Blog
POST/api/v1/blogs
{
"title": "Blog Title",
"content": "Blog Content",
"featureImage": "file_upload",
"contentImages": ["file_upload"],
"category": "category_id",
"isPublished": true
}
- Update Blog
PATCH/api/v1/blogs/:permalink
{
"title": "Updated Title",
"content": "Updated Content"
}
JWT-based authentication with:
- Access Token:
- Short-lived (1 day)
- Used for API requests
- Stored in HTTP-only cookie
- Refresh Token:
- Long-lived (10 days)
- Used to get new access tokens
- Stored in HTTP-only cookie
- Security Features:
- Password hashing (bcrypt)
- HTTP-only cookies
- CORS protection
- Rate limiting
- users
{
fullName: String,
username: String,
email: String,
password: String,
avatar: String,
role: String,
refreshToken: String
}
- blogs
{
title: String,
content: String,
permalink: String,
featureImage: String,
contentImages: [String],
author: ObjectId,
category: ObjectId,
status: String,
isPublished: Boolean
}
Using Cloudinary for media storage:
- Supported File Types:
- Images: JPG, PNG, GIF
- Max file size: 5MB
- Upload Process:
- Client uploads to server
- Server uploads to Cloudinary
- Cloudinary URL stored in database
# Connect to instance
ssh -i "key.pem" ec2-user@your-instance-ip
# Update system
sudo yum update -y
# Install Node.js
curl -sL https://rpm.nodesource.com/setup_22.x | sudo bash -
sudo yum install -y nodejs
# Install PM2
npm install pm2 -g
# Clone repository
git clone https://github.com/syedtasavour/TechTales.git
cd TechTales
# Install dependencies
npm install
# Setup environment
vim .env
# Start with PM2
pm2 start src/index.js --name techtales
# Install Nginx
sudo yum install nginx -y
# Configure Nginx
sudo vim /etc/nginx/conf.d/techtales.conf
# Example Nginx configuration
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
# Start Nginx
sudo systemctl start nginx
pip install awsebcli
eb init techtales --platform node.js --region us-east-1
eb create techtales-env
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
docker build -t techtales .
aws ecr create-repository --repository-name techtales
docker tag techtales:latest $AWS_ACCOUNT.dkr.ecr.$REGION.amazonaws.com/techtales
docker push $AWS_ACCOUNT.dkr.ecr.$REGION.amazonaws.com/techtales
- Input Validation
- XSS Protection (future implementation)
- CSRF Protection (future implementation)
- Rate Limiting (future implementation)
- Security Headers (future implementation)
- Data Encryption (future implementation)
Using Postman Collection:
- Import Collection:
- Import
backend.postman_collection.json
- Set environment variables
- Test Flow:
- Register user
- Login
- Create blog
- Test CRUD operations
- AWS CloudWatch setup
- Error tracking
- Performance monitoring
- Log management
Common Issues:
- Connection errors
- Authentication issues
- File upload problems
- Performance issues
Support:
- GitHub Issues
- Email: [email protected]
- Documentation: TechTales Docs
POST /api/v1/users/register
{
"fullName": "Admin User",
"username": "admin",
"email": "[email protected]",
"password": "secure_admin_password"
}
// Connect to MongoDB shell
mongosh "your_mongodb_uri"
// Switch to blog database
use blog
// Update user role to admin
db.users.updateOne(
{ email: "[email protected]" },
{ $set: { role: "ADMIN" } }
)
// Verify update
db.users.findOne({ email: "[email protected]" })
- Open MongoDB Compass
- Connect to your database
- Navigate to the 'blog' database
- Open the 'users' collection
- Find the user by email
- Update the role field to "ADMIN"
# Login as admin first
POST /api/v1/category
{
"name": "Uncategorized",
"description": "Default category for all posts",
"image": "optional_category_image"
}
// In MongoDB shell
use blog
// Find category ID
```javascript
// Check for the "Uncategorized" category
let category = db.categories.findOne({ name: "Uncategorized" });
if (!category) {
// Create "Uncategorized" category if it doesn't exist
category = db.categories.insertOne({
name: "Uncategorized",
description: "Default category for all posts",
image: "optional_category_image",
status: "approved" // optional, if you have a status field
});
print("Created default category 'Uncategorized'.");
} else {
print("Default category 'Uncategorized' already exists.");
}
// Add to .env file: DEFAULT_CATEGORY_ID=your_category_id
#### C. Update Application Code:
```javascript
// In src/constants.js
export const DEFAULT_CATEGORY_ID = process.env.DEFAULT_CATEGORY_ID || "your_category_id";
// In blog creation logic (src/controllers/blog.controller.js)
const category = req.body.category || DEFAULT_CATEGORY_ID;
Admin users can access:
- View all users
- Update user roles
- Disable/Enable users
- Approve/Reject blogs
- Manage categories
- Moderate comments
- Configure default settings
- Manage feature flags
- View system statistics
Admin API Endpoints:
The admin can access all endpoints without any checks, so you can assign any endpoint of authors or editors to the admin role as well, allowing them to access and manipulate all user data
# Blog Management
POST /api/v1/admin/blogs/status
{
"permalink": "blog-permalink",
"status": "approved"
}
# Category Management
POST /api/v1/admin/category/status
{
"name": "Category Name",
"status": "approved"
}
# Comment Moderation
GET /api/v1/admin/comments/pending
PATCH /api/v1/admin/comments/pending
{
"commentId": "comment_id",
"status": "approved"
}
- Use strong passwords
- Enable 2FA (future implementation)
- Regular password rotation
- IP restriction (future implementation)
- All admin routes are protected
- Role verification middleware
- Action logging
// Example audit log schema
{
action: String,
performedBy: ObjectId,
targetResource: String,
timestamp: Date,
details: Object
}
// Example logging middleware
const adminActionLogger = async (req, res, next) => {
const action = {
adminId: req.user._id,
action: req.method,
path: req.path,
timestamp: new Date(),
details: req.body
};
await AdminLog.create(action);
next();
};
- View all admin actions
- Filter by action type
- Export activity logs