329 lines
9.5 KiB
Markdown
329 lines
9.5 KiB
Markdown
|
|
# NestJS Serverless User CRUD Application
|
||
|
|
|
||
|
|
A professional serverless NestJS application with AWS Lambda, user CRUD operations, authentication, and comprehensive CI/CD pipeline.
|
||
|
|
|
||
|
|
## Features
|
||
|
|
|
||
|
|
- ☁️ **Serverless Architecture** - AWS Lambda with API Gateway
|
||
|
|
- 🔐 **Authentication & Authorization** - JWT-based authentication with role-based access control
|
||
|
|
- 👥 **User Management** - Complete CRUD operations for users
|
||
|
|
- 📝 **Post Management** - Create, read, update, and delete posts
|
||
|
|
- 🏗️ **Clean Architecture** - MVC + Clean Architecture patterns
|
||
|
|
- 🗄️ **Database** - PostgreSQL with Prisma ORM (RDS)
|
||
|
|
- 📚 **API Documentation** - Swagger/OpenAPI documentation
|
||
|
|
- 🛡️ **Security** - Helmet, CORS, rate limiting, input validation, WAF
|
||
|
|
- 🧪 **Testing Ready** - Jest configuration with CI/CD
|
||
|
|
- 🚀 **CI/CD Pipeline** - GitHub Actions with automated deployment
|
||
|
|
- 🌍 **Multi-Environment** - Dev, Staging, and Production environments
|
||
|
|
|
||
|
|
## Tech Stack
|
||
|
|
|
||
|
|
- **Framework**: NestJS
|
||
|
|
- **Runtime**: AWS Lambda (Node.js 18.x)
|
||
|
|
- **API Gateway**: AWS API Gateway
|
||
|
|
- **Database**: PostgreSQL (AWS RDS)
|
||
|
|
- **ORM**: Prisma
|
||
|
|
- **Authentication**: JWT with Passport
|
||
|
|
- **Validation**: class-validator & class-transformer
|
||
|
|
- **Documentation**: Swagger/OpenAPI
|
||
|
|
- **Security**: Helmet, bcryptjs, AWS WAF
|
||
|
|
- **Deployment**: Serverless Framework
|
||
|
|
- **CI/CD**: GitHub Actions
|
||
|
|
- **Infrastructure**: AWS (Lambda, RDS, VPC, CloudWatch)
|
||
|
|
|
||
|
|
## Project Structure
|
||
|
|
|
||
|
|
```
|
||
|
|
src/
|
||
|
|
├── common/ # Shared utilities and configurations
|
||
|
|
│ ├── database/ # Database configuration
|
||
|
|
│ ├── decorators/ # Custom decorators
|
||
|
|
│ ├── dto/ # Common DTOs
|
||
|
|
│ ├── guards/ # Custom guards
|
||
|
|
│ ├── interfaces/ # TypeScript interfaces
|
||
|
|
│ └── utils/ # Utility functions
|
||
|
|
├── modules/ # Feature modules
|
||
|
|
│ ├── auth/ # Authentication module
|
||
|
|
│ │ ├── controllers/ # Auth controllers
|
||
|
|
│ │ ├── dto/ # Auth DTOs
|
||
|
|
│ │ ├── guards/ # Auth guards
|
||
|
|
│ │ ├── services/ # Auth services
|
||
|
|
│ │ └── strategies/ # Passport strategies
|
||
|
|
│ ├── users/ # Users module
|
||
|
|
│ │ ├── controllers/ # User controllers
|
||
|
|
│ │ ├── dto/ # User DTOs
|
||
|
|
│ │ └── services/ # User services
|
||
|
|
│ └── posts/ # Posts module
|
||
|
|
│ ├── controllers/ # Post controllers
|
||
|
|
│ ├── dto/ # Post DTOs
|
||
|
|
│ └── services/ # Post services
|
||
|
|
├── app.module.ts # Root module
|
||
|
|
├── app.controller.ts # Root controller
|
||
|
|
├── app.service.ts # Root service
|
||
|
|
└── main.ts # Application entry point
|
||
|
|
```
|
||
|
|
|
||
|
|
## Getting Started
|
||
|
|
|
||
|
|
### Prerequisites
|
||
|
|
|
||
|
|
- Node.js (v18 or higher)
|
||
|
|
- AWS CLI configured
|
||
|
|
- PostgreSQL database (local or AWS RDS)
|
||
|
|
- npm or yarn
|
||
|
|
- Serverless Framework
|
||
|
|
|
||
|
|
### Installation
|
||
|
|
|
||
|
|
1. **Clone the repository**
|
||
|
|
```bash
|
||
|
|
git clone <repository-url>
|
||
|
|
cd nestjs-serverless-user-crud
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Install dependencies**
|
||
|
|
```bash
|
||
|
|
npm install
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **Set up environment variables**
|
||
|
|
```bash
|
||
|
|
# Copy environment template
|
||
|
|
cp env.dev .env
|
||
|
|
```
|
||
|
|
|
||
|
|
Update the `.env` file with your database credentials and JWT secret.
|
||
|
|
|
||
|
|
4. **Set up AWS resources**
|
||
|
|
```bash
|
||
|
|
# Run the AWS setup script
|
||
|
|
chmod +x scripts/setup-aws.sh
|
||
|
|
./scripts/setup-aws.sh dev
|
||
|
|
```
|
||
|
|
|
||
|
|
5. **Set up the database**
|
||
|
|
```bash
|
||
|
|
# Generate Prisma client
|
||
|
|
npm run prisma:generate
|
||
|
|
|
||
|
|
# Run database migrations
|
||
|
|
npm run prisma:migrate
|
||
|
|
|
||
|
|
# Seed the database (optional)
|
||
|
|
npm run prisma:seed
|
||
|
|
```
|
||
|
|
|
||
|
|
6. **Start the application**
|
||
|
|
```bash
|
||
|
|
# Local development
|
||
|
|
npm run start:dev
|
||
|
|
|
||
|
|
# Serverless offline
|
||
|
|
npm run start:serverless
|
||
|
|
|
||
|
|
# Deploy to AWS
|
||
|
|
npm run deploy:dev
|
||
|
|
```
|
||
|
|
|
||
|
|
## API Documentation
|
||
|
|
|
||
|
|
Once the application is running, you can access the Swagger documentation at:
|
||
|
|
- **Local Development**: http://localhost:3000/api/docs
|
||
|
|
- **Serverless Offline**: http://localhost:3000/api/docs
|
||
|
|
- **AWS Lambda**: https://your-api-gateway-url/api/docs (dev environment only)
|
||
|
|
|
||
|
|
## Serverless Deployment
|
||
|
|
|
||
|
|
### Environment Configuration
|
||
|
|
|
||
|
|
The application supports multiple environments:
|
||
|
|
- **Development** (`dev`) - For local development and testing
|
||
|
|
- **Staging** (`staging`) - For pre-production testing
|
||
|
|
- **Production** (`prod`) - For live production environment
|
||
|
|
|
||
|
|
### Deployment Commands
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Deploy to development
|
||
|
|
npm run deploy:dev
|
||
|
|
|
||
|
|
# Deploy to staging
|
||
|
|
npm run deploy:staging
|
||
|
|
|
||
|
|
# Deploy to production
|
||
|
|
npm run deploy:prod
|
||
|
|
|
||
|
|
# Remove deployment
|
||
|
|
npm run remove:dev
|
||
|
|
npm run remove:staging
|
||
|
|
npm run remove:prod
|
||
|
|
```
|
||
|
|
|
||
|
|
### Environment Variables
|
||
|
|
|
||
|
|
Set up the following environment variables for each environment:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Database
|
||
|
|
DATABASE_URL="postgresql://username:password@host:5432/database?schema=public"
|
||
|
|
|
||
|
|
# JWT Configuration
|
||
|
|
JWT_SECRET="your-super-secret-jwt-key"
|
||
|
|
JWT_EXPIRES_IN="7d"
|
||
|
|
|
||
|
|
# AWS Configuration
|
||
|
|
AWS_REGION="us-east-1"
|
||
|
|
VPC_SECURITY_GROUP_ID="sg-xxxxxxxxx"
|
||
|
|
VPC_SUBNET_ID_1="subnet-xxxxxxxxx"
|
||
|
|
VPC_SUBNET_ID_2="subnet-yyyyyyyyy"
|
||
|
|
```
|
||
|
|
|
||
|
|
## API Endpoints
|
||
|
|
|
||
|
|
### Authentication
|
||
|
|
- `POST /api/v1/auth/register` - Register a new user
|
||
|
|
- `POST /api/v1/auth/login` - Login user
|
||
|
|
- `POST /api/v1/auth/refresh` - Refresh access token
|
||
|
|
|
||
|
|
### Users
|
||
|
|
- `GET /api/v1/users` - Get all users (Admin/Moderator only)
|
||
|
|
- `GET /api/v1/users/profile` - Get current user profile
|
||
|
|
- `GET /api/v1/users/:id` - Get user by ID (Admin/Moderator only)
|
||
|
|
- `PATCH /api/v1/users/profile` - Update current user profile
|
||
|
|
- `PATCH /api/v1/users/:id` - Update user by ID (Admin only)
|
||
|
|
- `DELETE /api/v1/users/:id` - Delete user by ID (Admin only)
|
||
|
|
|
||
|
|
### Posts
|
||
|
|
- `GET /api/v1/posts` - Get all posts
|
||
|
|
- `GET /api/v1/posts/my-posts` - Get current user's posts
|
||
|
|
- `GET /api/v1/posts/:id` - Get post by ID
|
||
|
|
- `POST /api/v1/posts` - Create a new post
|
||
|
|
- `PATCH /api/v1/posts/:id` - Update post by ID
|
||
|
|
- `DELETE /api/v1/posts/:id` - Delete post by ID
|
||
|
|
|
||
|
|
## User Roles
|
||
|
|
|
||
|
|
- **USER**: Basic user with limited permissions
|
||
|
|
- **MODERATOR**: Can view all users and moderate content
|
||
|
|
- **ADMIN**: Full access to all resources
|
||
|
|
|
||
|
|
## Database Schema
|
||
|
|
|
||
|
|
### Users Table
|
||
|
|
- `id` - Unique identifier
|
||
|
|
- `email` - User email (unique)
|
||
|
|
- `username` - Username (unique)
|
||
|
|
- `password` - Hashed password
|
||
|
|
- `firstName` - First name
|
||
|
|
- `lastName` - Last name
|
||
|
|
- `isActive` - Account status
|
||
|
|
- `role` - User role (USER, MODERATOR, ADMIN)
|
||
|
|
- `createdAt` - Creation timestamp
|
||
|
|
- `updatedAt` - Last update timestamp
|
||
|
|
|
||
|
|
### Posts Table
|
||
|
|
- `id` - Unique identifier
|
||
|
|
- `title` - Post title
|
||
|
|
- `content` - Post content
|
||
|
|
- `published` - Publication status
|
||
|
|
- `authorId` - Foreign key to users table
|
||
|
|
- `createdAt` - Creation timestamp
|
||
|
|
- `updatedAt` - Last update timestamp
|
||
|
|
|
||
|
|
## Security Features
|
||
|
|
|
||
|
|
- **Password Hashing**: bcryptjs for secure password storage
|
||
|
|
- **JWT Authentication**: Secure token-based authentication
|
||
|
|
- **Role-based Access Control**: Different permissions for different roles
|
||
|
|
- **Input Validation**: Comprehensive validation using class-validator
|
||
|
|
- **Rate Limiting**: Protection against brute force attacks
|
||
|
|
- **CORS**: Configurable cross-origin resource sharing
|
||
|
|
- **Helmet**: Security headers for HTTP responses
|
||
|
|
|
||
|
|
## CI/CD Pipeline
|
||
|
|
|
||
|
|
The application includes a comprehensive CI/CD pipeline using GitHub Actions:
|
||
|
|
|
||
|
|
### Pipeline Stages
|
||
|
|
|
||
|
|
1. **Test & Lint** - Runs unit tests, e2e tests, and code linting
|
||
|
|
2. **Build** - Builds the application and uploads artifacts
|
||
|
|
3. **Deploy Dev** - Deploys to development environment (on develop branch)
|
||
|
|
4. **Deploy Staging** - Deploys to staging environment (on main branch)
|
||
|
|
5. **Deploy Production** - Deploys to production environment (manual approval)
|
||
|
|
6. **Security Scan** - Runs security audits and vulnerability scans
|
||
|
|
|
||
|
|
### GitHub Secrets
|
||
|
|
|
||
|
|
Configure the following secrets in your GitHub repository:
|
||
|
|
|
||
|
|
**Development Environment:**
|
||
|
|
- `AWS_ACCESS_KEY_ID_DEV`
|
||
|
|
- `AWS_SECRET_ACCESS_KEY_DEV`
|
||
|
|
- `DATABASE_URL_DEV`
|
||
|
|
- `JWT_SECRET_DEV`
|
||
|
|
- `VPC_SECURITY_GROUP_ID_DEV`
|
||
|
|
- `VPC_SUBNET_ID_1_DEV`
|
||
|
|
- `VPC_SUBNET_ID_2_DEV`
|
||
|
|
|
||
|
|
**Staging Environment:**
|
||
|
|
- `AWS_ACCESS_KEY_ID_STAGING`
|
||
|
|
- `AWS_SECRET_ACCESS_KEY_STAGING`
|
||
|
|
- `DATABASE_URL_STAGING`
|
||
|
|
- `JWT_SECRET_STAGING`
|
||
|
|
- `VPC_SECURITY_GROUP_ID_STAGING`
|
||
|
|
- `VPC_SUBNET_ID_1_STAGING`
|
||
|
|
- `VPC_SUBNET_ID_2_STAGING`
|
||
|
|
|
||
|
|
**Production Environment:**
|
||
|
|
- `AWS_ACCESS_KEY_ID_PROD`
|
||
|
|
- `AWS_SECRET_ACCESS_KEY_PROD`
|
||
|
|
- `DATABASE_URL_PROD`
|
||
|
|
- `JWT_SECRET_PROD`
|
||
|
|
- `VPC_SECURITY_GROUP_ID_PROD`
|
||
|
|
- `VPC_SUBNET_ID_1_PROD`
|
||
|
|
- `VPC_SUBNET_ID_2_PROD`
|
||
|
|
|
||
|
|
**Additional:**
|
||
|
|
- `SNYK_TOKEN` - For security scanning
|
||
|
|
|
||
|
|
## Development
|
||
|
|
|
||
|
|
### Available Scripts
|
||
|
|
|
||
|
|
- `npm run start:dev` - Start in development mode with hot reload
|
||
|
|
- `npm run start:serverless` - Start serverless offline
|
||
|
|
- `npm run build` - Build the application
|
||
|
|
- `npm run build:lambda` - Build for Lambda deployment
|
||
|
|
- `npm run start:prod` - Start in production mode
|
||
|
|
- `npm run test` - Run unit tests
|
||
|
|
- `npm run test:e2e` - Run end-to-end tests
|
||
|
|
- `npm run lint` - Run ESLint
|
||
|
|
- `npm run format` - Format code with Prettier
|
||
|
|
|
||
|
|
### Database Commands
|
||
|
|
|
||
|
|
- `npm run prisma:generate` - Generate Prisma client
|
||
|
|
- `npm run prisma:push` - Push schema changes to database
|
||
|
|
- `npm run prisma:migrate` - Run database migrations
|
||
|
|
- `npm run prisma:studio` - Open Prisma Studio
|
||
|
|
- `npm run prisma:seed` - Seed the database
|
||
|
|
|
||
|
|
### Deployment Scripts
|
||
|
|
|
||
|
|
- `./scripts/deploy.sh [environment]` - Deploy to specified environment
|
||
|
|
- `./scripts/setup-aws.sh [environment]` - Set up AWS resources
|
||
|
|
|
||
|
|
## Contributing
|
||
|
|
|
||
|
|
1. Fork the repository
|
||
|
|
2. Create a feature branch
|
||
|
|
3. Make your changes
|
||
|
|
4. Add tests if applicable
|
||
|
|
5. Submit a pull request
|
||
|
|
|
||
|
|
## License
|
||
|
|
|
||
|
|
This project is licensed under the MIT License.
|
||
|
|
|