RAG-based document question-answering app with:
- Frontend: React app (
frontend/) - Backend API: Node + Express (
server.js) - RAG Service: FastAPI + Hugging Face + FAISS (
rag-service/) - π Authentication: Role-based access control with JWT tokens
Upload a PDF, ask questions from its content, and generate a short summary. You can export the chat as CSV or TXT (plain text).
Issue Resolved: The system previously showed content from old PDFs when answering questions about new PDFs. This has been completely fixed.
For testing and understanding the fix, see:
- π START_HERE.md - Quick start (5 minutes)
- π§ͺ QUICK_TEST_GUIDE.md - Testing procedures
- π CONTEXT_LEAKAGE_FIX.md - Technical details
- π SOLUTION_SUMMARY.md - Complete overview
- Frontend uploads file to Node backend (
/upload) - Node forwards file path to FastAPI (
/process-pdf) - FastAPI detects file format (
.pdf,.docx,.txt,.md), loads and splits the document, builds vector index with embeddings - For
/askand/summarize, FastAPI retrieves relevant chunks and generates output with a Hugging Face model - π All API endpoints now require valid JWT authentication
.
βββ frontend/ # React UI
βββ rag-service/ # FastAPI RAG service
β βββ auth/ # Authentication system
β β βββ models.py # User models & roles
β β βββ schemas.py # Pydantic schemas
β β βββ security.py # JWT & password utils
β β βββ middleware.py # Auth middleware
β β βββ router.py # Auth endpoints
β βββ tests/ # Comprehensive test suite
β βββ database.py # Database configuration
β βββ main.py # FastAPI app with auth integration
βββ server.js # Node API gateway
βββ uploads/ # Uploaded files (runtime)
βββ CONTRIBUTING.md
- Node.js 18+ (LTS recommended)
- Python 3.10+
pip
From repository root:
npm install
cd frontend && npm install
cd ../rag-service && python -m pip install -r requirements.txtCreate .env in repo root (or edit existing):
# Optional model override
HF_GENERATION_MODEL=google/flan-t5-base
# REQUIRED: Authentication Configuration
SECRET_KEY=your-super-secret-jwt-key-change-this-in-production
ACCESS_TOKEN_EXPIRE_MINUTES=30
# Optional: Database Configuration (defaults to SQLite)
DATABASE_URL=sqlite:///./pdf_qa_bot.db
# For PostgreSQL: DATABASE_URL=postgresql://user:password@localhost/dbname
# For MySQL: DATABASE_URL=mysql://user:password@localhost/dbnameπ Security Configuration Notes:
SECRET_KEY: MUST be changed in production! Generate with:python -c "from secrets import token_urlsafe; print(token_urlsafe(32))"DATABASE_URL: Defaults to SQLite for development. Use PostgreSQL/MySQL for production.- Keep real secrets out of git.
The PDF QA Bot now includes comprehensive authentication and authorization:
- JWT-based Authentication: Secure token-based authentication
- Role-based Access Control: User and Admin roles with extensible permission system
- Password Security: bcrypt hashing with industry-standard practices
- API Protection: All PDF processing endpoints require authentication
| Role | Permissions |
|---|---|
| User | Upload PDFs, Ask questions, Summarize documents, View documents |
| Admin | All user permissions + Manage users, Delete documents, Compare documents, View all data |
After starting the application, create your first admin user:
# Register admin user via API
curl -X POST "http://localhost:5000/auth/register" \
-H "Content-Type: application/json" \
-d '{
"username": "admin",
"email": "admin@yourcompany.com",
"password": "your_secure_password_123",
"full_name": "System Administrator",
"role": "admin"
}'# Login to get JWT token
curl -X POST "http://localhost:5000/auth/login" \
-H "Content-Type: application/json" \
-d '{
"username": "admin",
"password": "your_secure_password_123"
}'
# Response:
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"token_type": "bearer",
"expires_in": 1800,
"user": {
"id": 1,
"username": "admin",
"email": "admin@yourcompany.com",
"role": "admin",
"is_active": true
}
}All PDF processing endpoints now require the Authorization header:
# Upload PDF with authentication
curl -X POST "http://localhost:5000/upload" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." \
-F "file=@your-document.pdf"
# Ask question with authentication
curl -X POST "http://localhost:5000/ask" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." \
-H "Content-Type: application/json" \
-d '{
"question": "What is the main topic?",
"doc_ids": ["doc-id-from-upload"]
}'POST /auth/register- Register new userPOST /auth/login- Login and get JWT token
GET /auth/me- Get current user profilePUT /auth/me- Update current user profilePOST /auth/change-password- Change password
GET /auth/users- List all usersGET /auth/users/{user_id}- Get user by IDPUT /auth/users/{user_id}- Update user by IDDELETE /auth/users/{user_id}- Delete userPOST /auth/users/{user_id}/activate- Activate userPOST /auth/users/{user_id}/deactivate- Deactivate user
For backward compatibility, a deprecated anonymous upload endpoint is available:
POST /upload/anonymous- Upload without authentication (β οΈ Deprecated, will be removed)
The React frontend automatically handles authentication:
- Login Flow: Users must login before accessing features
- Token Management: Automatic JWT token storage and refresh
- Route Protection: Authenticated routes with role-based access
- User Management: Admin interface for managing users
The authentication system uses these database tables:
-- Users table
CREATE TABLE users (
id INTEGER PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
hashed_password VARCHAR(255) NOT NULL,
full_name VARCHAR(100),
role VARCHAR(20) DEFAULT 'user',
is_active BOOLEAN DEFAULT true,
is_verified BOOLEAN DEFAULT false,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);β Implemented:
- JWT tokens with configurable expiration
- bcrypt password hashing
- Role-based permission system
- Input validation and sanitization
- Rate limiting on authentication endpoints
- SQL injection prevention with SQLAlchemy ORM
π Production Recommendations:
- Use PostgreSQL/MySQL instead of SQLite
- Configure HTTPS/TLS encryption
- Set up proper CORS policies
- Implement session management
- Add API rate limiting
- Monitor authentication logs
- Regular security audits HF_GENERATION_MODEL=google/flan-t5-base
Notes:
- `OPENAI_API_KEY` is not required for current Hugging Face RAG flow.
- Keep real secrets out of git.
## 3) Run the App (3 terminals)
### Terminal A β RAG service (port 5000)
```bash
cd rag-service
uvicorn main:app --host 0.0.0.0 --port 5000 --reload
# from the repository root (where server.js lives)
cd <your-repo-directory>
node server.js# navigate into the frontend subfolder from the repo root
cd frontend
npm startOpen: http://localhost:3000
For production deployment or simplified development setup, you can use Docker Compose to run all services with proper health checks and dependency management.
# Build and start all services
docker-compose up --build
# Or run in background
docker-compose up --build -d
# Check service status
docker-compose psAll services include health and readiness endpoints for monitoring and debugging:
# Basic health check
curl http://localhost:4000/healthz
# Readiness check (includes RAG service connectivity)
curl http://localhost:4000/readyz# Basic health check
curl http://localhost:5000/healthz
# Readiness check (includes model and component status)
curl http://localhost:5000/readyz# View service health in Docker Compose
docker-compose ps
# View health check logs
docker-compose logs gateway
docker-compose logs rag-service- π’ Healthy: Service is up and responding
- π‘ Starting: Service is starting up (grace period)
- π΄ Unhealthy: Service failed multiple health checks
The Docker Compose setup ensures:
- RAG service starts and is healthy before gateway starts
- Gateway waits for RAG service to be ready before accepting requests
- Frontend waits for gateway to be healthy before starting
- Automatic restart on health check failures
POST /upload(multipart form-data, field:file) - π Auth RequiredPOST /ask({ "question": "..." }) - π Auth RequiredPOST /summarize({}) - π Auth Required
POST /upload- Upload and process PDFPOST /process-pdf- Process PDF from file pathPOST /ask- Ask questions about documentsPOST /summarize- Summarize documentsPOST /compare- Compare multiple documentsGET /documents- List processed documentsGET /similarity-matrix- Get document similarity matrixPOST /upload(multipart form-data, field:file) β accepts.pdf,.docx,.txt,.mdPOST /ask({ "question": "..." })POST /summarize({})
POST /auth/register- Register new userPOST /auth/login- Login and get JWT token
GET /auth/me- Get current user profilePUT /auth/me- Update profilePOST /auth/change-password- Change password
GET /auth/users- List all usersGET /auth/users/{user_id}- Get user detailsPUT /auth/users/{user_id}- Update userDELETE /auth/users/{user_id}- Delete userPOST /auth/users/{user_id}/activate- Activate userPOST /auth/users/{user_id}/deactivate- Deactivate user
POST /upload/anonymous- Upload without auth (will be removed)
Interactive API docs: http://localhost:5000/docs
-
Cannot POST /uploadfrom frontend- Restart frontend dev server after config changes:
npm start - Ensure Node backend is running on port
4000
- Restart frontend dev server after config changes:
-
Upload fails / connection refused
- Ensure FastAPI is running on port
5000
- Ensure FastAPI is running on port
-
Slow first request
- Hugging Face model downloads on first run (can take time)
-
Port already in use
- Stop old processes or change ports consistently in frontend/backend/service
-
401 Unauthorized errors
- Ensure you're logged in and have a valid JWT token
- Check that Authorization header is properly formatted:
Bearer <token> - Token may have expired (default: 30 minutes) - login again
-
403 Forbidden errors
- Your user role may not have sufficient permissions
- Contact admin to check your user role and permissions
- Some endpoints require admin role
-
Database connection errors
- Check DATABASE_URL in .env file
- Ensure database file has proper permissions (SQLite)
- For PostgreSQL/MySQL: verify connection credentials
-
JWT Secret Key warnings
- Change SECRET_KEY in .env file from default value
- Use a securely generated random key for production
-
User registration fails
- Username/email may already exist
- Password must be at least 8 characters
- Check required fields are filled
Run the test suite to verify authentication is working:
cd rag-service
pip install pytest pytest-asyncio httpx pytest-mock
pytest tests/ -vIf you need to reset the user database:
cd rag-service
rm -f pdf_qa_bot.db # Remove SQLite database
# Database will be recreated on next startup- RAG index is in-memory (rebuilds after restart)
- Summarization and QA use retrieved context from the last processed PDF
- π Authentication: SQLite database persists users across restarts
- JWT tokens expire after 30 minutes by default (configurable)
- Role-based permissions are extensible for future role types
The project includes comprehensive test coverage for authentication and API endpoints.
cd rag-service
# Install test dependencies
pip install pytest pytest-asyncio httpx pytest-mock
# Run all tests
pytest tests/ -v
# Run specific test categories
pytest tests/test_auth_endpoints.py -v # Authentication tests
pytest tests/test_security.py -v # Security utilities tests
pytest tests/test_middleware.py -v # Middleware tests
pytest tests/test_models.py -v # Database model tests
pytest tests/test_protected_endpoints.py -v # API protection tests
# Run with coverage
pip install pytest-cov
pytest tests/ --cov=. --cov-report=html- Authentication Tests: User registration, login, token validation
- Authorization Tests: Role-based access control, permissions
- Security Tests: Password hashing, JWT token management
- API Protection Tests: Endpoint security, rate limiting
- Database Tests: User models, relationships, queries
- Integration Tests: End-to-end authentication flows
Tests use a separate SQLite database (test_pdf_qa_bot.db) that's automatically created and cleaned up. No configuration needed for basic testing.
- Default SECRET_KEY is acceptable for local development
- SQLite database is fine for testing and development
- CORS is configured permissively for frontend integration
- Change SECRET_KEY: Generate a secure random key
- Use Production Database: PostgreSQL or MySQL recommended
- Configure CORS: Restrict allowed origins to your domain
- Enable HTTPS: Use TLS encryption for all communications
- Environment Variables: Use proper secrets management
- Update Dependencies: Keep all packages up to date
- Rate Limiting: Configure appropriate rate limits
- Monitoring: Set up authentication and error logging
The authentication system is designed for future extension:
- Additional Roles: Easy to add MODERATOR, PREMIUM_USER, etc.
- Custom Permissions: Granular permission system expandable
- OAuth Integration: Architecture supports OAuth2/OIDC providers
- Multi-tenant: Database schema ready for organization support
- Audit Logging: Framework in place for comprehensive audit trails
See ADVANCED_ISSUES.md for critical security, performance, and architecture issues that need attention before production deployment.
Refer to CONTRIBUTING.md for detailed instructions on creating a branch, naming conventions, committing changes, and submitting pull requests.