Skip to content
Open
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
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.git
node_modules
*.log
tmp/
118 changes: 118 additions & 0 deletions DOCKER_SETUP_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Fusion Docker Setup Summary

## Overview
Successfully configured Docker containers for both Fusion Server (Django backend) and Fusion Client (React frontend) with proper networking and environment configuration.

## Services Running

### 1. Database (PostgreSQL)
- **Container**: `fusion_db_1`
- **Status**: Up and healthy
- **Port**: 5432
- **Database**: fusionlab
- **User**: fusion_admin
- **Password**: hello123 (default)

### 2. Backend Server (Django)
- **Container**: `fusion_app_1`
- **Status**: Up and running
- **Port**: 8000
- **URL**: http://localhost:8000
- **Environment**: Development settings with environment variable support

### 3. Frontend Server (React + Nginx)
- **Container**: `fusion_frontend_1`
- **Status**: Up and running
- **Port**: 3000
- **URL**: http://localhost:3000
- **Build**: Production build served via Nginx

## Configuration Files Created

### 1. Fusion-client/Dockerfile
- Multi-stage build for React application
- Uses Node.js 18 Alpine for building
- Nginx Alpine for serving production build
- Handles husky dependency issues with `--ignore-scripts`

### 2. Fusion-client/nginx.conf
- Configures Nginx to serve React app on port 3000
- Sets up API proxy to backend at http://app:8000
- Handles static file caching and routing

### 3. Updated Fusion/docker-compose.yml
- Added frontend service with proper dependencies
- Configured health checks for database
- Set up environment variables for both services
- Proper networking between containers

### 4. Updated Fusion/docker-entrypoint.sh
- Added database connection wait logic using Python/psycopg2
- Runs migrations before starting Django server
- Handles database readiness properly

### 5. Updated Fusion/FusionIIIT/Fusion/settings/development.py
- Added environment variable support for database configuration
- Uses `os.environ.get()` for DB_HOST, DB_NAME, DB_USER, DB_PASSWORD

## How to Use

### Start All Services
```bash
cd Fusion
docker-compose up --build
```

### Access the Applications
- **Frontend**: http://localhost:3000
- **Backend API**: http://localhost:8000

### Stop Services
```bash
cd Fusion
docker-compose down
```

### Clean Up (Remove Volumes)
```bash
cd Fusion
docker-compose down -v
```

## Notes

1. **Database Migrations**: Some Django migrations may need to be run manually if there are schema issues
2. **Environment Variables**: Database credentials can be customized via environment variables
3. **Port Conflicts**: Ensure ports 5432, 8000, and 3000 are available on the host
4. **Local PostgreSQL**: If you have a local PostgreSQL server running, it may conflict with the container

## Troubleshooting

### Port Already in Use
```bash
# Stop local PostgreSQL if running
sudo systemctl stop postgresql

# Or change ports in docker-compose.yml
```

### Database Connection Issues
- Check that the database container is healthy
- Verify environment variables are set correctly
- Ensure the database is ready before the app starts

### Frontend Build Issues
- The build process ignores husky scripts to avoid dependency issues
- Production build is optimized and minified
- Nginx serves static files efficiently

## Architecture
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Frontend │ │ Backend │ │ Database │
│ (Port 3000) │───▶│ (Port 8000) │───▶│ (Port 5432) │
│ React + Nginx │ │ Django │ │ PostgreSQL │
└─────────────────┘ └─────────────────┘ └─────────────────┘
```

The setup provides a complete development environment with proper separation of concerns and production-ready configuration.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ENV PYTHONUNBUFFERED 1
COPY requirements.txt $FUSION_HOME

# install dependencies
RUN pip install --upgrade pip && pip install -r requirements.txt
RUN pip install -r requirements.txt

# copy api directory to docker's work directory.
COPY . $FUSION_HOME
Expand Down
87 changes: 87 additions & 0 deletions FusionIIIT/Fusion/api_auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
from rest_framework.authtoken.models import Token
from rest_framework import status
from django.contrib.auth import authenticate

class CustomTokenObtainPairView(APIView):
permission_classes = [] # Allow unauthenticated access

def post(self, request, *args, **kwargs):
username = request.data.get('username')
password = request.data.get('password')

if not username or not password:
return Response({'error': 'Username and password are required'}, status=status.HTTP_400_BAD_REQUEST)

user = authenticate(username=username, password=password)
if user is None:
return Response({'error': 'Invalid credentials'}, status=status.HTTP_401_UNAUTHORIZED)

# Use Django REST framework Token authentication instead of JWT
token, created = Token.objects.get_or_create(user=user)

return Response({
'token': token.key,
'user': {
'id': user.id,
'username': user.username,
'email': user.email,
}
})

class AuthMeView(APIView):
permission_classes = [IsAuthenticated]

def get(self, request):
user = request.user
role_str = "student"
try:
role_str = str(user.extrainfo.user_type).lower()
except:
pass

# Normalize roles so the frontend can reliably distinguish student vs faculty.
# In this dataset, faculty users typically have user_type = 'staff'.
if role_str == "staff":
role_str = "faculty"

# Give them comprehensive permissions so the sidebar populates fully for testing
accessible_modules = {
role_str: {
"home": True,
"online_cms": True,
"course_registration": True,
"program_and_curriculum": True,
"mess_management": True,
"visitor_hostel": True,
"phc": True,
"fts": True,
"spacs": True,
"complaint_management": True,
"placement_cell": True,
"department": True,
"rspc": True,
"inventory_management": True,
"purchase_and_store": True,
"hr": True,
"examinations": True,
"gymkhana": True,
"iwd": True,
"hostel_management": True,
"other_academics": True,
"course_management": True,
"patent_management": True,
}
}

return Response({
'id': user.id,
'username': user.username,
'email': user.email,
'role': role_str,
'roles': [role_str],
'accessibleModules': accessible_modules
})
Binary file added FusionIIIT/Fusion/db.sqlite3
Binary file not shown.
37 changes: 32 additions & 5 deletions FusionIIIT/Fusion/settings/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,15 @@
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
CLIENT_ID = '187004491411-frc3j36n04o9k0imgnbl02qg42vkq36f.apps.googleusercontent.com'
CLIENT_SECRET = 'enHu3RD0yBvCM_9C0HQmEp0z'
# SECURITY WARNING: Google OAuth credentials MUST be set via environment variables
# Never commit credentials to version control
CLIENT_ID = os.environ.get('GOOGLE_CLIENT_ID', '')
CLIENT_SECRET = os.environ.get('GOOGLE_CLIENT_SECRET', '')

if not CLIENT_ID or not CLIENT_SECRET:
import warnings
warnings.warn('Google OAuth credentials not configured. Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET environment variables.')

# SECURITY WARNING: don't run with debug turned on in production!

# Google authentication
Expand Down Expand Up @@ -150,6 +156,7 @@
'django_cleanup.apps.CleanupConfig',
'django_unused_media',
'rest_framework',
'rest_framework_simplejwt',
'rest_framework.authtoken',
]

Expand Down Expand Up @@ -245,7 +252,7 @@

USE_L10N = False

USE_TZ = False
USE_TZ = True

SITE_ID = 1
# Static files (CSS, JavaScript, Images)
Expand Down Expand Up @@ -277,5 +284,25 @@
YOUTUBE_DATA_API_KEY = 'api_key'


CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_ALLOW_ALL = False
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000",
"http://127.0.0.1:3000",
"http://localhost:5173",
"http://127.0.0.1:5173",
"http://localhost:5174",
"http://127.0.0.1:5174",
# Add your production domain here
]
ALLOW_PASS_RESET = True


REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}

from datetime import timedelta
28 changes: 19 additions & 9 deletions FusionIIIT/Fusion/settings/development.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,38 @@
import os
from Fusion.settings.common import *
from datetime import timedelta
import warnings

DEBUG = True

SECRET_KEY = '=&w9due426k@l^ju1=s1)fj1rnpf0ok8xvjwx+62_nc-f12-8('
# WARNING: Use strong secret key in production. Generate with: python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
if not os.environ.get('SECRET_KEY'):
warnings.warn('SECRET_KEY not set in environment. Using development key. NEVER use in production!')
SECRET_KEY = os.environ.get('SECRET_KEY', 'dev-key-only-for-development-change-in-production')

ALLOWED_HOSTS = ['*']
# Development: Allow localhost only. Set ALLOWED_HOSTS in production via environment
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost,127.0.0.1').split(',')

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'fusionlab',
'HOST': os.environ.get("DB_HOST", default='localhost'),
'USER': 'fusion_admin',
'PASSWORD': 'hello123',
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME', 'fusionlab'),
'USER': os.environ.get('DB_USER', 'fusion_admin'),
'PASSWORD': os.environ.get('DB_PASSWORD', os.environ.get('POSTGRES_PASSWORD', 'postgres_default')),
'HOST': os.environ.get('DB_HOST', 'localhost'),
'PORT': os.environ.get('DB_PORT', '5432'),
}
}

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
),
}

if DEBUG:
Expand Down
Loading
Loading