Fix: Rename directory to remove & character causing shell issues
Renamed ebook_backend&admin_panel to ebook_backend_admin_panel The & character was being interpreted by shell as background process operator, causing 'Dockerfile not found' errors in Coolify.
This commit is contained in:
979
ebook_backend_admin_panel/README.md
Normal file
979
ebook_backend_admin_panel/README.md
Normal file
@@ -0,0 +1,979 @@
|
||||
# 📚 Ebook Coupon Management System
|
||||
|
||||
A comprehensive enterprise-grade FastAPI application for managing ebook coupon codes with an admin dashboard interface and translation file management system.
|
||||
|
||||
[](https://www.python.org/)
|
||||
[](https://fastapi.tiangolo.com/)
|
||||
[](https://www.postgresql.org/)
|
||||
[](LICENSE)
|
||||
|
||||
---
|
||||
|
||||
## 📑 Table of Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Features](#features)
|
||||
- [Technology Stack](#technology-stack)
|
||||
- [Project Structure](#project-structure)
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Installation & Setup](#installation--setup)
|
||||
- [Environment Configuration](#environment-configuration)
|
||||
- [Running the Application](#running-the-application)
|
||||
- [API Endpoints](#api-endpoints)
|
||||
- [Admin Dashboard](#admin-dashboard)
|
||||
- [Database Schema](#database-schema)
|
||||
- [Testing](#testing)
|
||||
- [Deployment](#deployment)
|
||||
---
|
||||
|
||||
## 🎯 Overview
|
||||
|
||||
The Ebook Coupon Management System is a production-ready web application designed to manage ebook coupon codes efficiently. It provides a secure admin interface for generating, managing, and tracking coupon usage, along with translation file management capabilities.
|
||||
|
||||
**Key Highlights:**
|
||||
- ✅ Automatic database initialization on first run
|
||||
- ✅ Auto-creates admin user from environment variables
|
||||
- ✅ RESTful API with comprehensive documentation
|
||||
- ✅ Real-time coupon generation and validation
|
||||
- ✅ Excel file support for bulk operations
|
||||
- ✅ Translation file management system
|
||||
- ✅ Comprehensive test suite included
|
||||
- ✅ Production-ready logging and error handling
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Features
|
||||
|
||||
### 🔐 Authentication & Authorization
|
||||
- **Secure Admin Login**: Session-based authentication with HTTP-only cookies
|
||||
- **Auto Admin Creation**: First-time setup automatically creates admin user
|
||||
- **Password Hashing**: Bcrypt password encryption
|
||||
- **Logout Functionality**: Clean session termination
|
||||
|
||||
### 🎫 Coupon Management
|
||||
|
||||
#### Generate Coupons
|
||||
- **Single Generation**: Create one coupon code at a time
|
||||
- **Bulk Generation**: Generate multiple coupons in one operation
|
||||
- **Unique Codes**: 10-character alphanumeric codes (uppercase)
|
||||
- **Automatic Storage**: Codes saved to database with metadata
|
||||
|
||||
#### Manage Coupons
|
||||
- **List All Coupons**: Paginated listing with usage statistics
|
||||
- **Search Functionality**: Case-insensitive search by coupon code
|
||||
- **Usage Tracking**: One time coupon code usage and timestamps
|
||||
- **Delete Coupons**: Remove unwanted or expired codes
|
||||
- **Add Manual Codes**: Add specific coupon codes manually
|
||||
|
||||
#### Bulk Operations
|
||||
- **Excel Upload**: Upload multiple coupons from Excel files (.xlsx, .xls)
|
||||
- **Duplicate Detection**: Automatically skips existing codes
|
||||
- **Validation**: Ensures data integrity during bulk upload
|
||||
|
||||
#### Coupon Validation
|
||||
- **Code Verification**: Check if coupon exists and is valid
|
||||
- **Usage Validation**: Prevent reuse of single-use coupons
|
||||
- **Mark as Used**: Track when and how coupons are redeemed
|
||||
|
||||
### 🌐 Translation File Management
|
||||
- **Upload Translation Files**: Admin can upload Excel translation files
|
||||
- **Download Translations**: Retrieve uploaded translation files
|
||||
- **Delete Translations**: Remove existing translation files
|
||||
- **Status Check**: Verify if translation file exists
|
||||
- **Metadata Storage**: Preserves original filename information
|
||||
- **File Validation**: Ensures only valid Excel files are accepted
|
||||
|
||||
### 🖥️ Admin Dashboard
|
||||
- **Modern UI**: Clean, responsive interface built with vanilla JavaScript
|
||||
- **Real-time Updates**: Live data refresh without page reload
|
||||
- **File Upload**: Drag-and-drop support for Excel files
|
||||
- **Pagination**: Efficient browsing of large coupon lists
|
||||
- **Search Interface**: Quick search functionality
|
||||
- **Statistics Display**: View total coupons and usage
|
||||
|
||||
### 📊 System Features
|
||||
- **Health Monitoring**: `/health` endpoint for system checks
|
||||
- **Database Status**: Real-time database connection monitoring
|
||||
- **Automatic Migrations**: Tables created automatically on startup
|
||||
- **Logging System**: Structured JSON logging with rotation
|
||||
- **Error Handling**: Comprehensive exception handling
|
||||
- **Request Tracking**: Unique request IDs for tracing
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Technology Stack
|
||||
|
||||
### Backend
|
||||
| Technology | Purpose | Version |
|
||||
|------------|---------|---------|
|
||||
| **FastAPI** | Web framework | Latest |
|
||||
| **Uvicorn** | ASGI server | Latest |
|
||||
| **SQLAlchemy** | ORM | 2.x |
|
||||
| **PostgreSQL** | Database | 12+ |
|
||||
| **Pydantic** | Data validation | 2.x |
|
||||
| **Passlib** | Password hashing | Latest |
|
||||
| **Bcrypt** | Encryption | 4.0.1 |
|
||||
| **Python-Jose** | JWT handling | Latest |
|
||||
|
||||
### Frontend
|
||||
| Technology | Purpose |
|
||||
|------------|---------|
|
||||
| **HTML5** | Structure |
|
||||
| **CSS3** | Styling |
|
||||
| **Vanilla JavaScript** | Interactivity |
|
||||
| **Fetch API** | HTTP requests |
|
||||
|
||||
### Development & Testing
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
| **Pytest** | Testing framework |
|
||||
| **HTTPx** | Async HTTP client |
|
||||
| **Python-dotenv** | Environment management |
|
||||
|
||||
---
|
||||
|
||||
## 📁 Project Structure
|
||||
|
||||
```
|
||||
ebook_extension-feature-admin-dashboard/
|
||||
│
|
||||
├── admin-backend/ # Backend API application
|
||||
│ ├── models/ # Database models
|
||||
│ │ ├── user.py # Admin user model
|
||||
│ │ └── coupon.py # Coupon model
|
||||
│ │
|
||||
│ ├── routes/ # API routes
|
||||
│ │ └── auth.py # All API endpoints
|
||||
│ │
|
||||
│ ├── utils/ # Utility modules
|
||||
│ │ ├── auth.py # Authentication utilities
|
||||
│ │ ├── coupon_utils.py # Coupon generation
|
||||
│ │ ├── exceptions.py # Custom exceptions
|
||||
│ │ ├── logger.py # Logging configuration
|
||||
│ │ ├── template_loader.py # Template utilities
|
||||
│ │ └── timezone_utils.py # Timezone handling
|
||||
│ │
|
||||
│ ├── tests/ # Test suite
|
||||
│ │ ├── conftest.py # Test configuration
|
||||
│ │ ├── test_auth_routes.py # Auth endpoint tests
|
||||
│ │ ├── test_coupon_routes.py # Coupon endpoint tests
|
||||
│ │ ├── test_main.py # Main app tests
|
||||
│ │ ├── test_models.py # Model tests
|
||||
│ │ ├── test_schemas.py # Schema tests
|
||||
│ │ ├── test_translation_routes.py # Translation tests
|
||||
│ │ └── test_utils.py # Utility tests
|
||||
│ │
|
||||
│ ├── logs/ # Application logs
|
||||
│ │ ├── app.log # General logs
|
||||
│ │ └── error.log # Error logs
|
||||
│ │
|
||||
│ ├── translationfile/ # Translation storage
|
||||
│ │ └── translation.xlsx # Uploaded translation file
|
||||
│ │
|
||||
│ ├── main.py # FastAPI application
|
||||
│ ├── init_db.py # Database initialization
|
||||
│ ├── schemas.py # Pydantic schemas
|
||||
│ ├── manage_test_db.py # Test database manager
|
||||
│ └── pytest.ini # Pytest configuration
|
||||
│
|
||||
├── admin-frontend/ # Frontend files
|
||||
│ ├── admin_login.html # Login page
|
||||
│ ├── admin_login.js # Login logic
|
||||
│ ├── admin_dashboard.html # Dashboard UI
|
||||
│ └── admin_dashboard.js # Dashboard logic
|
||||
│
|
||||
├── .env.example # Environment template
|
||||
├── .gitignore # Git ignore rules
|
||||
├── requirements.txt # Python dependencies
|
||||
├── README.md
|
||||
└── start.sh # Startup script
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Prerequisites
|
||||
|
||||
Before installing, ensure you have the following:
|
||||
|
||||
- **Python**: Version 3.10 or higher
|
||||
- **PostgreSQL**: Version 12 or higher
|
||||
- **pip**: Python package manager
|
||||
- **Virtual Environment**: `venv` or `virtualenv`
|
||||
- **Git**: For cloning the repository
|
||||
|
||||
### System Requirements
|
||||
- **OS**: Linux, macOS, or Windows
|
||||
- **RAM**: Minimum 2GB
|
||||
- **Disk Space**: Minimum 500MB
|
||||
|
||||
---
|
||||
|
||||
## 💻 Installation & Setup
|
||||
|
||||
### Step 1: Clone the Repository
|
||||
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd ebook_extension-feature-admin-dashboard
|
||||
```
|
||||
|
||||
### Step 2: Create Virtual Environment
|
||||
|
||||
```bash
|
||||
# Create virtual environment
|
||||
python3 -m venv .venv
|
||||
|
||||
# Activate virtual environment
|
||||
# On Linux/Mac:
|
||||
source .venv/bin/activate
|
||||
|
||||
# On Windows:
|
||||
.venv\Scripts\activate
|
||||
```
|
||||
|
||||
### Step 3: Install Dependencies
|
||||
|
||||
```bash
|
||||
pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### Step 4: Set Up PostgreSQL Database
|
||||
|
||||
#### Create Database
|
||||
```bash
|
||||
# Option 1: Using psql
|
||||
sudo -u postgres psql -c "CREATE DATABASE ebook_db;"
|
||||
|
||||
# Option 2: Using createdb
|
||||
sudo -u postgres createdb ebook_db
|
||||
|
||||
# Option 3: Connect to PostgreSQL and create manually
|
||||
sudo -u postgres psql
|
||||
postgres=# CREATE DATABASE ebook_db;
|
||||
postgres=# \q
|
||||
```
|
||||
|
||||
#### Verify Database Creation
|
||||
```bash
|
||||
sudo -u postgres psql -c "\l" | grep ebook_db
|
||||
```
|
||||
|
||||
### Step 5: Configure Environment Variables
|
||||
|
||||
```bash
|
||||
# Copy example environment file
|
||||
cp .env.example .env
|
||||
|
||||
# Edit with your settings
|
||||
nano .env # or your preferred editor
|
||||
```
|
||||
|
||||
**Required Configuration:**
|
||||
- Update `DATABASE_URL` if using different credentials
|
||||
- Change `ADMIN_PASSWORD` from default
|
||||
- Generate strong `SECRET_KEY` for production
|
||||
|
||||
### Step 6: Initialize Database (Automatic)
|
||||
|
||||
The application automatically:
|
||||
- Creates all required tables on first run
|
||||
- Creates admin user from `.env` credentials
|
||||
- Validates database connection
|
||||
|
||||
**No manual database setup required!**
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Environment Configuration
|
||||
|
||||
### Environment Variables Explained
|
||||
|
||||
Create a `.env` file in the project root with these variables:
|
||||
|
||||
#### Database Configuration
|
||||
```bash
|
||||
# PostgreSQL connection string
|
||||
DATABASE_URL=postgresql://username:password@host:port/database
|
||||
|
||||
# Test database (for running tests)
|
||||
TEST_DATABASE_URL=postgresql://username:password@host:port/test_database
|
||||
```
|
||||
|
||||
#### Security Configuration
|
||||
```bash
|
||||
# Secret key for JWT and session encryption
|
||||
# Generate with: python -c "import secrets; print(secrets.token_urlsafe(32))"
|
||||
SECRET_KEY=your-super-secret-key-change-this-in-production
|
||||
|
||||
# Debug mode (set to false in production)
|
||||
DEBUG=true
|
||||
|
||||
# Environment: development, staging, production
|
||||
ENVIRONMENT=development
|
||||
```
|
||||
|
||||
#### Admin Credentials
|
||||
```bash
|
||||
# Auto-created admin user on first run
|
||||
# IMPORTANT: Change these before production deployment!
|
||||
ADMIN_USERNAME=admin
|
||||
ADMIN_PASSWORD=admin@123
|
||||
```
|
||||
|
||||
#### Application Configuration
|
||||
```bash
|
||||
# Application details
|
||||
APP_NAME=Ebook Coupon Management System
|
||||
APP_VERSION=1.0.0
|
||||
|
||||
# CORS allowed origins (comma-separated)
|
||||
CORS_ORIGINS=http://localhost:3000,http://localhost:8000,http://127.0.0.1:8000
|
||||
|
||||
# Trusted hosts
|
||||
TRUSTED_HOSTS=*
|
||||
```
|
||||
|
||||
#### Logging Configuration
|
||||
```bash
|
||||
# Log level: DEBUG, INFO, WARNING, ERROR, CRITICAL
|
||||
LOG_LEVEL=INFO
|
||||
|
||||
# Log file paths (relative to admin-backend)
|
||||
LOG_FILE=logs/app.log
|
||||
ERROR_LOG_FILE=logs/error.log
|
||||
```
|
||||
|
||||
#### File Upload Configuration
|
||||
```bash
|
||||
# Maximum file size in bytes (10MB default)
|
||||
MAX_FILE_SIZE=10485760
|
||||
|
||||
# Allowed file types
|
||||
ALLOWED_FILE_TYPES=.xlsx,.xls
|
||||
```
|
||||
|
||||
#### Server Configuration
|
||||
```bash
|
||||
# Server binding
|
||||
HOST=0.0.0.0
|
||||
PORT=8000
|
||||
```
|
||||
|
||||
### Security Best Practices
|
||||
|
||||
🔒 **For Production:**
|
||||
1. Generate strong `SECRET_KEY`: `python -c "import secrets; print(secrets.token_urlsafe(32))"`
|
||||
2. Change `ADMIN_PASSWORD` to a strong password (12+ characters)
|
||||
3. Set `DEBUG=false`
|
||||
4. Set `ENVIRONMENT=production`
|
||||
5. Update `CORS_ORIGINS` to specific domains
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Running the Application
|
||||
|
||||
### Method 1: Using Startup Script (Recommended)
|
||||
|
||||
```bash
|
||||
./start.sh
|
||||
```
|
||||
|
||||
This script automatically:
|
||||
- Checks for `.env` file (creates from example if missing)
|
||||
- Activates virtual environment
|
||||
- Installs/updates dependencies
|
||||
- Starts the application with auto-reload
|
||||
|
||||
### Method 2: Manual Start
|
||||
|
||||
```bash
|
||||
# Navigate to backend directory
|
||||
cd admin-backend
|
||||
|
||||
# Activate virtual environment
|
||||
source ../.venv/bin/activate
|
||||
|
||||
# Start the server
|
||||
uvicorn main:app --reload --host 0.0.0.0 --port 8000
|
||||
```
|
||||
|
||||
### Verify Application is Running
|
||||
|
||||
```bash
|
||||
# Check health endpoint
|
||||
curl http://localhost:8000/health
|
||||
|
||||
# Expected response:
|
||||
# {
|
||||
# "status": "healthy",
|
||||
# "timestamp": 1762246309.91,
|
||||
# "version": "1.0.0",
|
||||
# "environment": "development",
|
||||
# "database_status": "connected"
|
||||
# }
|
||||
```
|
||||
|
||||
### Access Points
|
||||
|
||||
| Service | URL | Description |
|
||||
|---------|-----|-------------|
|
||||
| **API** | http://localhost:8000 | Main API endpoint |
|
||||
| **Admin Login** | http://localhost:8000/login | Admin login page |
|
||||
| **Admin Dashboard** | http://localhost:8000/ | Main dashboard (requires login) |
|
||||
| **API Docs** | http://localhost:8000/docs | Swagger UI documentation |
|
||||
| **ReDoc** | http://localhost:8000/redoc | Alternative API docs |
|
||||
| **Health Check** | http://localhost:8000/health | System health status |
|
||||
|
||||
### Default Login Credentials
|
||||
|
||||
```
|
||||
Username: admin
|
||||
Password: admin@123
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📡 API Endpoints
|
||||
|
||||
### Authentication Endpoints
|
||||
|
||||
#### Admin Login
|
||||
```http
|
||||
POST /admin/login
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"username": "admin",
|
||||
"password": "admin@123"
|
||||
}
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"status": "success"
|
||||
}
|
||||
```
|
||||
|
||||
#### Admin Logout
|
||||
```http
|
||||
POST /admin/logout
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"status": "success"
|
||||
}
|
||||
```
|
||||
|
||||
### Coupon Management Endpoints
|
||||
|
||||
#### Generate Single Coupon
|
||||
```http
|
||||
POST /generate
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
mode=single
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"code": "A1B2C3D4E5"
|
||||
}
|
||||
```
|
||||
|
||||
#### Generate Bulk Coupons
|
||||
```http
|
||||
POST /generate
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
mode=bulk&count=100
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"codes": ["CODE1", "CODE2", ...]
|
||||
}
|
||||
```
|
||||
|
||||
#### List All Coupons
|
||||
```http
|
||||
GET /list?page=1&limit=20
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"codes": [
|
||||
{
|
||||
"code": "A1B2C3D4E5",
|
||||
"used_at": "2025-11-04 10:30:00 CEST",
|
||||
"usage_count": 1
|
||||
}
|
||||
],
|
||||
"total": 100,
|
||||
"page": 1,
|
||||
"limit": 20,
|
||||
"total_pages": 5
|
||||
}
|
||||
```
|
||||
|
||||
#### Search Coupons
|
||||
```http
|
||||
GET /search-codes?query=A1B2
|
||||
|
||||
Response: 200 OK
|
||||
[
|
||||
{
|
||||
"code": "A1B2C3D4E5",
|
||||
"used": 1,
|
||||
"usage_count": 1,
|
||||
"used_at": "2025-11-04 10:30:00 CEST"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### Check Specific Coupon
|
||||
```http
|
||||
GET /check-code/A1B2C3D4E5
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"code": "A1B2C3D4E5",
|
||||
"used": 1
|
||||
}
|
||||
```
|
||||
|
||||
#### Verify and Use Coupon
|
||||
```http
|
||||
POST /verify
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"code": "A1B2C3D4E5"
|
||||
}
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"message": "Coupon verified",
|
||||
"used_at": "2025-11-04 10:30:00 CEST"
|
||||
}
|
||||
```
|
||||
|
||||
#### Add Manual Coupon
|
||||
```http
|
||||
POST /add-code
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"code": "CUSTOM123",
|
||||
"usage": 0
|
||||
}
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"message": "Code added successfully"
|
||||
}
|
||||
```
|
||||
|
||||
#### Delete Coupon
|
||||
```http
|
||||
DELETE /delete-code/A1B2C3D4E5
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"message": "Code deleted successfully"
|
||||
}
|
||||
```
|
||||
|
||||
#### Upload Coupons from Excel
|
||||
```http
|
||||
POST /upload-codes
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"codes": [
|
||||
{"code": "CODE1", "usage": 0},
|
||||
{"code": "CODE2", "usage": 1}
|
||||
]
|
||||
}
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"uploaded": 2,
|
||||
"skipped": 0,
|
||||
"total": 2
|
||||
}
|
||||
```
|
||||
|
||||
### Translation File Endpoints
|
||||
|
||||
#### Upload Translation File
|
||||
```http
|
||||
POST /upload-translations
|
||||
Content-Type: multipart/form-data
|
||||
|
||||
file: <translation.xlsx>
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"message": "Translation file uploaded successfully",
|
||||
"filename": "translation.xlsx"
|
||||
}
|
||||
```
|
||||
|
||||
#### Download Translation File
|
||||
```http
|
||||
GET /download-translation
|
||||
|
||||
Response: 200 OK
|
||||
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||
Content-Disposition: attachment; filename="translation.xlsx"
|
||||
```
|
||||
|
||||
#### Delete Translation File
|
||||
```http
|
||||
DELETE /delete-translation
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"message": "Translation file deleted successfully"
|
||||
}
|
||||
```
|
||||
|
||||
#### Check Translation Status
|
||||
```http
|
||||
GET /translations/status
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"file_exists": true,
|
||||
"file_name": "translation.xlsx"
|
||||
}
|
||||
```
|
||||
|
||||
#### Get Latest Translation (Legacy)
|
||||
```http
|
||||
GET /translations/latest
|
||||
|
||||
Response: 200 OK
|
||||
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||
```
|
||||
|
||||
### System Endpoints
|
||||
|
||||
#### Health Check
|
||||
```http
|
||||
GET /health
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"status": "healthy",
|
||||
"timestamp": 1762246309.91,
|
||||
"version": "1.0.0",
|
||||
"environment": "development",
|
||||
"database_status": "connected"
|
||||
}
|
||||
```
|
||||
|
||||
#### Root Endpoint
|
||||
```http
|
||||
GET /
|
||||
|
||||
Response: 302 Found
|
||||
Location: /login (if not logged in)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🖥️ Admin Dashboard
|
||||
|
||||
### Features
|
||||
|
||||
1. **Login Page** (`/login`)
|
||||
- Secure authentication form
|
||||
- Session-based login
|
||||
- Error handling
|
||||
|
||||
2. **Dashboard** (`/`)
|
||||
- Coupon generation (single/bulk)
|
||||
- Coupon listing with pagination
|
||||
- Search functionality
|
||||
- File upload for bulk operations
|
||||
- Translation file management
|
||||
- Statistics display
|
||||
|
||||
### Usage
|
||||
|
||||
1. **Login**: Navigate to `http://localhost:8000/login`
|
||||
2. **Enter Credentials**: Use admin username and password from `.env`
|
||||
3. **Dashboard Access**: Automatically redirected to dashboard on success
|
||||
4. **Generate Coupons**: Use the generation form
|
||||
5. **Upload Files**: Drag and drop or browse for Excel files
|
||||
6. **Manage Translations**: Upload, download, or delete translation files
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ Database Schema
|
||||
|
||||
### Table: `admin_users`
|
||||
|
||||
| Column | Type | Constraints | Description |
|
||||
|--------|------|-------------|-------------|
|
||||
| id | INTEGER | PRIMARY KEY | Auto-increment ID |
|
||||
| username | STRING | UNIQUE, NOT NULL | Admin username |
|
||||
| password_hash | STRING | NOT NULL | Bcrypt hashed password |
|
||||
| created_at | DATETIME | DEFAULT NOW | Account creation timestamp |
|
||||
|
||||
### Table: `coupon_codes`
|
||||
|
||||
| Column | Type | Constraints | Description |
|
||||
|--------|------|-------------|-------------|
|
||||
| id | INTEGER | PRIMARY KEY | Auto-increment ID |
|
||||
| code | STRING | UNIQUE | Coupon code |
|
||||
| usage_count | INTEGER | DEFAULT 0 | Number of times used |
|
||||
| created_at | DATETIME | DEFAULT NOW | Creation timestamp |
|
||||
| used_at | DATETIME | NULLABLE | Last usage timestamp |
|
||||
|
||||
**Timezone**: All timestamps use Europe/Bratislava timezone for creation, Asia/Kolkata for usage.
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
### Run All Tests
|
||||
|
||||
```bash
|
||||
cd admin-backend
|
||||
source ../.venv/bin/activate
|
||||
pytest
|
||||
```
|
||||
|
||||
### Run Specific Test Files
|
||||
|
||||
```bash
|
||||
# Test auth routes
|
||||
pytest tests/test_auth_routes.py
|
||||
|
||||
# Test coupon routes
|
||||
pytest tests/test_coupon_routes.py
|
||||
|
||||
# Test models
|
||||
pytest tests/test_models.py
|
||||
```
|
||||
|
||||
### Run with Coverage
|
||||
|
||||
```bash
|
||||
pytest --cov=. --cov-report=html
|
||||
```
|
||||
|
||||
### Test Database
|
||||
|
||||
Tests use a separate test database configured in `TEST_DATABASE_URL`.
|
||||
|
||||
---
|
||||
|
||||
## 🚢 Production Deployment
|
||||
|
||||
### Pre-Deployment Checklist
|
||||
|
||||
- [ ] Set `DEBUG=false`
|
||||
- [ ] Set `ENVIRONMENT=production`
|
||||
- [ ] Change `ADMIN_PASSWORD` to strong password
|
||||
- [ ] Generate secure `SECRET_KEY`
|
||||
- [ ] Update `CORS_ORIGINS` with production domains
|
||||
- [ ] Configure PostgreSQL with SSL
|
||||
- [ ] Set up Nginx reverse proxy
|
||||
- [ ] Configure SSL/TLS certificates
|
||||
- [ ] Enable firewall rules
|
||||
- [ ] Set up automated backups
|
||||
- [ ] Configure monitoring and logging
|
||||
|
||||
### Production Environment Variables
|
||||
|
||||
```bash
|
||||
# Database
|
||||
DATABASE_URL=postgresql://dbuser:strong_password@localhost:5432/ebook_prod
|
||||
|
||||
# Security
|
||||
SECRET_KEY=<generate-with: python -c "import secrets; print(secrets.token_urlsafe(32))">
|
||||
DEBUG=false
|
||||
ENVIRONMENT=production
|
||||
|
||||
# Admin (change after first login!)
|
||||
ADMIN_USERNAME=admin
|
||||
ADMIN_PASSWORD=<strong-password-here>
|
||||
|
||||
# CORS
|
||||
CORS_ORIGINS=https://yourdomain.com,https://www.yourdomain.com
|
||||
TRUSTED_HOSTS=yourdomain.com,www.yourdomain.com
|
||||
|
||||
# Application
|
||||
APP_NAME=Ebook Coupon Management System
|
||||
APP_VERSION=1.0.0
|
||||
LOG_LEVEL=WARNING
|
||||
|
||||
# Server
|
||||
HOST=0.0.0.0
|
||||
PORT=8000
|
||||
```
|
||||
|
||||
### Deployment with Systemd
|
||||
|
||||
1. **Install Gunicorn**
|
||||
```bash
|
||||
pip install gunicorn
|
||||
```
|
||||
|
||||
2. **Create Systemd Service File**
|
||||
```bash
|
||||
sudo nano /etc/systemd/system/ebook-api.service
|
||||
```
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Ebook Coupon Management System API
|
||||
After=network.target postgresql.service
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
User=www-data
|
||||
Group=www-data
|
||||
WorkingDirectory=/var/www/ebook_extension-feature-admin-dashboard/admin-backend
|
||||
Environment="PATH=/var/www/ebook_extension-feature-admin-dashboard/.venv/bin"
|
||||
EnvironmentFile=/var/www/ebook_extension-feature-admin-dashboard/.env
|
||||
ExecStart=/var/www/ebook_extension-feature-admin-dashboard/.venv/bin/gunicorn \
|
||||
-w 4 \
|
||||
-k uvicorn.workers.UvicornWorker \
|
||||
--bind 0.0.0.0:8000 \
|
||||
main:app
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
3. **Enable and Start Service**
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable ebook-api
|
||||
sudo systemctl start ebook-api
|
||||
sudo systemctl status ebook-api
|
||||
```
|
||||
|
||||
### Nginx Reverse Proxy
|
||||
|
||||
1. **Install Nginx**
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install nginx
|
||||
```
|
||||
|
||||
2. **Create Nginx Configuration**
|
||||
```bash
|
||||
sudo nano /etc/nginx/sites-available/ebook-api
|
||||
```
|
||||
|
||||
```nginx
|
||||
upstream ebook_backend {
|
||||
server 127.0.0.1:8000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name yourdomain.com www.yourdomain.com;
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name yourdomain.com www.yourdomain.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
|
||||
add_header Strict-Transport-Security "max-age=31536000" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
|
||||
client_max_body_size 10M;
|
||||
|
||||
location / {
|
||||
proxy_pass http://ebook_backend;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
location /static {
|
||||
alias /var/www/ebook_extension-feature-admin-dashboard/admin-frontend;
|
||||
expires 30d;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. **Enable Site**
|
||||
```bash
|
||||
sudo ln -s /etc/nginx/sites-available/ebook-api /etc/nginx/sites-enabled/
|
||||
sudo nginx -t
|
||||
sudo systemctl restart nginx
|
||||
```
|
||||
|
||||
### Logs and Debugging
|
||||
|
||||
```bash
|
||||
# Application logs
|
||||
tail -f admin-backend/logs/app.log
|
||||
|
||||
# Error logs
|
||||
tail -f admin-backend/logs/error.log
|
||||
|
||||
# Search for errors
|
||||
grep -i error admin-backend/logs/app.log
|
||||
|
||||
# Enable debug mode
|
||||
DEBUG=true uvicorn main:app
|
||||
```
|
||||
|
||||
### Quick Reference Commands
|
||||
|
||||
```bash
|
||||
# Start application (development)
|
||||
./start.sh
|
||||
|
||||
# Start application (production)
|
||||
gunicorn -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000 main:app
|
||||
|
||||
# Stop application
|
||||
pkill -f "uvicorn main:app"
|
||||
|
||||
# Check if running
|
||||
ps aux | grep uvicorn
|
||||
|
||||
# View health status
|
||||
curl http://localhost:8000/health
|
||||
|
||||
# Database operations
|
||||
sudo -u postgres psql -d ebook_db
|
||||
```
|
||||
---
|
||||
## 📄 License
|
||||
|
||||
This project is licensed under the MIT License - see the LICENSE file for details.
|
||||
|
||||
---
|
||||
|
||||
## 🙏 Acknowledgments
|
||||
|
||||
- FastAPI team for the excellent framework
|
||||
- SQLAlchemy team for the powerful ORM
|
||||
- All contributors and users
|
||||
|
||||
---
|
||||
|
||||
## 📞 Support
|
||||
|
||||
For support and questions:
|
||||
- Review application logs: `admin-backend/logs/`
|
||||
- Check troubleshooting section above
|
||||
- Open an issue on GitHub
|
||||
|
||||
---
|
||||
Reference in New Issue
Block a user