Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 30 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,47 +9,62 @@ on:
jobs:
backend-test:
runs-on: ubuntu-latest

services:
mongo:
image: mongo:latest
image: mongo:6
ports:
- 27017:27017

steps:
- uses: actions/checkout@v3
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.13'
- name: Install dependencies
python-version: "3.13"

- name: Install backend dependencies
run: |
python -m pip install --upgrade pip
pip install -r backend/requirements.txt

- name: Start Backend
env:
MONGODB_URL: mongodb://localhost:27017
SECRET_KEY: testsecret
MONGO_URI: mongodb://localhost:27017
SECRET_KEY: test-secret
run: |
cd backend
python -m uvicorn app.main:app --host 0.0.0.0 --port 8001 &
sleep 10 # Wait for startup
- name: Run Verification
uvicorn app.main:app --host 0.0.0.0 --port 8000 &
sleep 8

- name: Verify Backend APIs
run: |
cd backend
python verify_backend.py
export PYTHONPATH=$(pwd)
python app/routes/api/v2/verify_db.py

frontend-build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up Node
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
node-version: "24"
cache: "npm"
cache-dependency-path: frontend/package-lock.json

- name: Install frontend dependencies
run: |
cd frontend
npm ci
- name: Build

- name: Build frontend
run: |
cd frontend
npm run build
158 changes: 99 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,12 @@
# Scalable REST API with Authentication & Role-Based Access

### *Built using Python & FastAPI*
## Project Overview
This project is a scalable backend system built using Python (FastAPI) with JWT authentication and role-based access control, along with a basic frontend UI to interact with the APIs.

The system allows users to register, log in, and perform CRUD operations on a secondary entity (Tasks) while enforcing proper authorization rules. It is designed with security, modularity, and scalability in mind.

---

## Tech Stack

### Backend
- Language: Python
- Framework: FastAPI
- Authentication: JWT (JSON Web Tokens)
- Password Hashing: bcrypt (passlib)
- ORM: SQLAlchemy
- Database: PostgreSQL / SQLite (for demo)
- Validation: Pydantic
- API Documentation: Swagger (OpenAPI)

### Frontend
- Framework: React.js (Vite) / Vanilla JavaScript
- HTTP Client: Axios / Fetch API
- Auth Storage: LocalStorage (JWT)

---

## Project Structure

```
Expand All @@ -47,12 +28,33 @@ backend/
│ │ ├── users.py
│ │ └── tasks.py
│ ├── db/
│ │ ├── session.py
│ │ └── base.py
│ └── utils/
│ └── role_checker.py
│ │ └── mongodb.py
│ ├── utils/
│ │ └── logger.py
│ └── Scalability_Guide.md
├── Dockerfile
├── requirements.txt
└── README.md
docs/
├── Back-End.md
├── Front-End.md
└── DB_Schema.md
frontend/
├── src/
│ ├── api/
│ ├── components/
│ ├── context/
│ ├── pages/
│ ├── App.tsx
│ └── main.tsx
├── package.json
├── vite.config.ts
├── Dockerfile
└── README.md
.github/
└── workflows/
└── ci.yml
docker-compose.yml
```

---
Expand All @@ -77,28 +79,39 @@ Authorization: Bearer <token>

## Database Schema

### User Table
| Field | Type |
|-----------------|------------------|
| id | Integer (PK) |
| email | String (Unique) |
| hashed_password | String |
| role | USER / ADMIN |
| created_at | Timestamp |

### Task Table
| Field | Type |
|------------|-------------------|
| id | Integer (PK) |
| title | String |
| description| String |
| owner_id | Foreign Key (User)|
| created_at | Timestamp |
### User Schema
```
{
"id": "Integer (PK)",
"name": "String",
"email": "String (Unique)",
"permission": "String",
"role": "USER / ADMIN",
"hashed_password": "String",
"created_at": "Timestamp"
}
```

### Task Schema
```
{
"id": "Integer (PK)",
"title": "String",
"description": "String",
"owner_id": "Foreign Key (User)",
"created_at": "Timestamp"
}
```

---

## API Endpoints

### Health Check APIs
| Method | Endpoint | Description |
|--------|------------------------|------------------|
| GET | /api/v1/health | Health check |

### Auth APIs
| Method | Endpoint | Description |
|--------|------------------------|------------------|
Expand All @@ -108,18 +121,37 @@ Authorization: Bearer <token>
### Task APIs
| Method | Endpoint | Access |
|--------|----------------------|--------|
| POST | /api/v1/tasks | User |
| GET | /api/v1/tasks | User |
| PUT | /api/v1/tasks/{id} | Owner |
| GET | /api/v1/tasks | User |
| POST | /api/v1/tasks | User |
| PUT | /api/v1/tasks/{id} | Owner |
| DELETE | /api/v1/tasks/{id} | Admin |
| GET | /api/v1/tasks | User |

### User APIs
| Method | Endpoint | Access |
|--------|----------------------|--------|
| GET | /api/v1/users | User |
| POST | /api/v1/users | User |
| PUT | /api/v1/users/{id} | Owner |
| DELETE | /api/v1/users/{id} | Admin |
| GET | /api/v1/users | Admin |

---

## Docker Support

The project includes Dockerfiles for both backend and frontend.
Run both services using:

**``` docker-compose up --build ```**

---

## API Documentation
Swagger UI is available at:

```bash
http://localhost:8000/docs
http://localhost:8001/docs
```

A Postman collection is also provided for API testing.
Expand Down Expand Up @@ -147,12 +179,14 @@ A Postman collection is also provided for API testing.

### Backend Setup
```bash
git clone <repo-url>
git clone https://github.com/HackyCoder0951/authdb.git
python -m venv .venv
cd backend
python -m venv venv
source venv/bin/activate
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload
# Ensure MongoDB is running locally or set MONGO_URI in .env
uvicorn app.main:app --host 0.0.0.0 --port 8001

```

### Frontend Setup
Expand All @@ -174,12 +208,24 @@ npm run dev
---

## Scalability & Future Improvements
- Microservices-based architecture
- Redis caching for frequently accessed data
- Load balancing using NGINX
- **Scalability Guide**: A detailed guide (`app/Scalability_Guide.md`) is included to assist with understanding microservices, caching (Redis), and load balancing.
- Microservices-based architecture (Proposed)
- Redis caching for frequently accessed data (Proposed)
- Load balancing using NGINX (Proposed)
- **Advanced Logging**: Custom logging utility for better observability.
- Docker containerization
- API rate limiting
- CI/CD pipeline integration
## Detailed Documentation
For deep dives into specific areas, please refer to the `docs/` directory:
- **[Backend Architecture](docs/Back-End.md)**: Logic flow, Auth, and Task management.
- **[Frontend Architecture](docs/Front-End.md)**: Component structure and State management.
- **[Database Schema](docs/DB_Schema.md)**: ERD diagrams and Collection details.

## CI/CD Pipeline
Automated testing and build pipelines are implemented using **GitHub Actions**.
- **Config**: `.github/workflows/ci.yml`
- **Backend**: Runs unit tests and verifies API health.
- **Frontend**: Installs dependencies and checks build status.

---

Expand All @@ -192,9 +238,3 @@ npm run dev
- API documentation

---

## Author
Backend Developer Intern Assignment

Built using Python & FastAPI

10 changes: 10 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY app ./app

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8001"]
23 changes: 6 additions & 17 deletions backend/app/main.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import logging
from fastapi import FastAPI
from app.routes.api.v1 import auth, tasks, users, health
from fastapi.middleware.cors import CORSMiddleware
from app.core.config import settings
from app.db.mongodb import mongodb
from app.routes import auth, tasks, users
from app.utils.logger import setup_logging

# Configure Logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)
logger = logging.getLogger(__name__)
# Configure Logging using custom utility
logger = setup_logging()

app = FastAPI(title=settings.PROJECT_NAME)
app = FastAPI(title=settings.PROJECT_NAME, redirect_slashes=False)

# CORS
app.add_middleware(
Expand All @@ -36,14 +32,7 @@ async def shutdown_db_client():
await mongodb.close_database_connection()
logger.info("Database connection closed.")

# Routes
@app.get("/health", tags=["Health"])
async def health_check():
is_connected = await mongodb.check_connection()
if is_connected:
return {"status": "ok", "database": "connected"}
return {"status": "error", "database": "disconnected"}

app.include_router(health.router, prefix="/api/v1", tags=["Health"])
app.include_router(auth.router, prefix="/api/v1/auth", tags=["Auth"])
app.include_router(tasks.router, prefix="/api/v1/tasks", tags=["Tasks"])
app.include_router(users.router, prefix="/api/v1/users", tags=["Users"])
Expand Down
File renamed without changes.
12 changes: 12 additions & 0 deletions backend/app/routes/api/v1/health.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from fastapi import APIRouter
from app.db.mongodb import mongodb

router = APIRouter()

# Routes
@router.get("/health", tags=["Health"])
async def health_check():
is_connected = await mongodb.check_connection()
if is_connected:
return {"status": "ok", "database": "connected"}
return {"status": "error", "database": "disconnected"}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import asyncio
from motor.motor_asyncio import AsyncIOMotorClient
from app.core.config import settings
# import certifi

async def verify():
print(f"Connecting to {settings.MONGODB_URL}...")
Expand All @@ -13,4 +12,4 @@ async def verify():
print(f"FAILURE: {e}")

if __name__ == "__main__":
asyncio.run(verify())
asyncio.run(verify())
Loading