diff --git a/config/middleware/site_middleware.py b/config/middleware/site_middleware.py new file mode 100644 index 0000000..9e3a169 --- /dev/null +++ b/config/middleware/site_middleware.py @@ -0,0 +1,32 @@ +""" +Domain-based URL Configuration Middleware + +This middleware detects the request domain and routes to the appropriate +URLconf (URL configuration) for each site: +- Dovoodi domains → config.urls_dovoodi +- Imam Javad domains → config.urls_imamjavad +""" + + +class SiteMiddleware: + """ + Middleware to route requests to different URL configurations based on domain. + + This allows each domain to have clean /admin/ URLs instead of path-based + differentiation (/imam-javad/admin vs /dovoodi/admin). + """ + + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + host = request.get_host() + + # Check if the request is from Dovoodi domain + if 'dovodi' in host or 'dovoodi' in host: + request.urlconf = 'config.urls_dovoodi' + # Otherwise, use Imam Javad configuration (default) + else: + request.urlconf = 'config.urls_imamjavad' + + return self.get_response(request) diff --git a/config/settings/base.py b/config/settings/base.py index ff262cf..07a0be2 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -116,6 +116,7 @@ PHONENUMBER_DEFAULT_FORMAT = 'INTERNATIONAL' AUTH_USER_MODEL = "account.User" MIDDLEWARE = [ + 'config.middleware.site_middleware.SiteMiddleware', # Must be first to route by domain 'django.middleware.security.SecurityMiddleware', "whitenoise.middleware.WhiteNoiseMiddleware", 'django.contrib.sessions.middleware.SessionMiddleware', diff --git a/config/urls.py b/config/urls.py index e78de5c..8b6c43b 100644 --- a/config/urls.py +++ b/config/urls.py @@ -93,19 +93,17 @@ api_patterns = [ ] +# Base URL patterns (common to all domains) +# These patterns are shared by both Imam Javad and Dovoodi sites urlpatterns = [ - path("admin/", HomeView.as_view(), name="home"), path("i18n/", include("django.conf.urls.i18n")), - - # path('admin/', admin.site.urls), path('api/', include(api_patterns)), - # path('test/', include('apps.api.urls')) path('oneapi-translation/', oneapi_translate), path('admin/filer/', include('filer.urls')), - path('filer/', include('filer.urls')), - + path('filer/', include('filer.urls')), ] -# Protected swagger URL patterns + +# Protected swagger URL patterns (to be used in domain-specific configs) swagger_urlpatterns = [ path('swagger-auth/', SwaggerTokenAuthView.as_view(), name='swagger-token-auth'), path('swagger-auth/clear/', clear_swagger_auth, name='clear-swagger-auth'), @@ -118,15 +116,6 @@ swagger_urlpatterns = [ name='schema-redoc'), ] -urlpatterns+= i18n_patterns( - path("imam-javad/admin/", project_admin_site.urls), - path("dovoodi/admin/", dovoodi_admin_site.urls ), - path('docs/', CustomAPIDocumentationView.as_view(), name='docs-index'), - *swagger_urlpatterns, - path('admin/filer/', include('filer.urls')), - path('filer/', include('filer.urls')), -) - if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/config/urls_dovoodi.py b/config/urls_dovoodi.py new file mode 100644 index 0000000..8fb77a6 --- /dev/null +++ b/config/urls_dovoodi.py @@ -0,0 +1,26 @@ +""" +URL configuration for Dovoodi domain +This configuration is loaded when accessing from dovodi.* or dovoodi.* domains +""" +from django.urls import path, include +from django.conf.urls.i18n import i18n_patterns +from config.urls import urlpatterns as base_urlpatterns, swagger_urlpatterns +from utils.admin import dovoodi_admin_site +from apps.api.views import CustomAPIDocumentationView + + +# Combine base patterns with Dovoodi specific admin +urlpatterns = base_urlpatterns + i18n_patterns( + # Admin panel accessible at /admin/ (Django will redirect to /en/admin/ or /fa/admin/) + path("admin/", dovoodi_admin_site.urls), + + # API documentation + path('docs/', CustomAPIDocumentationView.as_view(), name='docs-index'), + + # Swagger and API documentation + *swagger_urlpatterns, + + # Filer (Django file manager) + path('admin/filer/', include('filer.urls')), + path('filer/', include('filer.urls')), +) diff --git a/config/urls_imamjavad.py b/config/urls_imamjavad.py new file mode 100644 index 0000000..e5bface --- /dev/null +++ b/config/urls_imamjavad.py @@ -0,0 +1,26 @@ +""" +URL configuration for Imam Javad domain +This configuration is loaded when accessing from imamjavad.* domains +""" +from django.urls import path, include +from django.conf.urls.i18n import i18n_patterns +from config.urls import urlpatterns as base_urlpatterns, swagger_urlpatterns +from utils.admin import project_admin_site +from apps.api.views import CustomAPIDocumentationView + + +# Combine base patterns with Imam Javad specific admin +urlpatterns = base_urlpatterns + i18n_patterns( + # Admin panel accessible at /admin/ (Django will redirect to /en/admin/ or /fa/admin/) + path("admin/", project_admin_site.urls), + + # API documentation + path('docs/', CustomAPIDocumentationView.as_view(), name='docs-index'), + + # Swagger and API documentation + *swagger_urlpatterns, + + # Filer (Django file manager) + path('admin/filer/', include('filer.urls')), + path('filer/', include('filer.urls')), +) diff --git a/nginx/dovodi.conf b/nginx/dovodi.conf index 481b381..be2fecf 100644 --- a/nginx/dovodi.conf +++ b/nginx/dovodi.conf @@ -1,10 +1,10 @@ server { listen 80; listen 443 ssl; - server_name dovodi.nwhco.ir; - # ssl_certificate /etc/nginx/certs/nwhco.pem; - # ssl_certificate_key /etc/nginx/certs/nwhco.key; - # include /etc/nginx/options-ssl-nginx.conf; + server_name dovodi.nwhco.ir dovodi.newhorizonco.uk; + ssl_certificate /etc/nginx/certs/nwhco.pem; + ssl_certificate_key /etc/nginx/certs/nwhco.key; + include /etc/nginx/options-ssl-nginx.conf; client_max_body_size 500M; client_body_timeout 600s; @@ -14,17 +14,6 @@ server { proxy_read_timeout 600s; # ========== Django Admin Paths (باید قبل از location / باشند) ========== - - # Add this inside the 'server' block of the existing config - - location /agent/ { - proxy_pass http://88.99.212.243:8098; - 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; - } - # با prefix زبانی location /en/dovoodi/ { diff --git a/nginx/imamjavad.conf b/nginx/imamjavad.conf index 81501bf..6f98fac 100644 --- a/nginx/imamjavad.conf +++ b/nginx/imamjavad.conf @@ -1,15 +1,38 @@ +# ======================================== +# Imam Javad Platform - Nginx Configuration +# Single Domain - Clean Architecture +# ======================================== + +# ========== Upstream Definitions ========== +upstream django_backend { + server 88.99.212.243:8010; + keepalive 32; +} + +upstream nextjs_frontend { + server 88.99.212.243:7226; + keepalive 32; +} + +upstream chat_service { + server 88.99.212.243:8020; + keepalive 32; +} + +# ========== Proxy Settings (Reusable) ========== +# Include this file or copy these settings +# /etc/nginx/snippets/proxy-params.conf + server { listen 80; -<<<<<<< HEAD - # listen 443 ssl; -======= listen 443 ssl; ->>>>>>> a1b3ddf (Add Nginx configuration files for dovoodi and imamjavad services) - server_name imamjavad.nwhco.ir imamjavad.newhorizonco.uk; + server_name imamjavad.nwhco.ir imamjavad.newhorizonco.uk; + # ssl_certificate /etc/nginx/certs/nwhco.pem; # ssl_certificate_key /etc/nginx/certs/nwhco.key; # include /etc/nginx/options-ssl-nginx.conf; - + + # ========== Global Settings ========== client_max_body_size 500M; client_body_timeout 600s; client_header_timeout 60s; @@ -17,167 +40,141 @@ server { proxy_send_timeout 600s; proxy_read_timeout 600s; - # ========== Django Admin Paths (باید قبل از location / باشند) ========== - - # با prefix زبانی - location /en/imam-javad/ { - proxy_pass http://88.99.212.243:8010; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # ========== 1. Static Files (Highest Priority) ========== + location /static/ { + alias /home/app/web/imam_javad_staticfiles/; + expires 30d; + add_header Cache-Control "public, immutable"; + access_log off; + } + + location /media/ { + alias /home/app/web/imam_javad_mediafiles/; + expires 30d; + add_header Cache-Control "public, immutable"; + add_header Access-Control-Allow-Origin *; + add_header Access-Control-Allow-Methods "GET, OPTIONS"; + access_log off; + } + + # ========== 2. Next.js Assets ========== + location /_next/ { + proxy_pass http://nextjs_frontend; + proxy_http_version 1.1; 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; - client_max_body_size 1200M; + expires 1y; + add_header Cache-Control "public, immutable"; + access_log off; } - location /fa/imam-javad/ { - proxy_pass http://88.99.212.243:8010; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # ========== 3. API Endpoints ========== + location /api/ { + proxy_pass http://django_backend; + proxy_http_version 1.1; 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; + proxy_set_header Authorization $http_authorization; + proxy_pass_header Authorization; client_max_body_size 1200M; } - # بدون prefix زبانی (fallback) - location /imam-javad/ { - proxy_pass http://88.99.212.243:8010; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # ========== 4. Chat Service (WebSocket) ========== + location /chat { + proxy_pass http://chat_service; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 1200M; + + # WebSocket timeouts + proxy_read_timeout 3600s; + proxy_send_timeout 3600s; } - # ========== Admin Entry Points ========== - - location = /admin { - return 301 /admin/; - } - - location /admin/ { - proxy_pass http://88.99.212.243:8010; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # ========== 5. i18n Language Switcher ========== + location /i18n/ { + proxy_pass http://django_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; - client_max_body_size 1200M; } - location = /admin/logout { - return 301 /en/imam-javad/admin/logout/; - } - - # مسیر عمومی admin (سازگاری با config قدیمی) - location /en/admin { - proxy_pass http://88.99.212.243:8010; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # ========== 6. Django Admin Panel (Single Pattern) ========== + # Matches: /en/imam-javad/admin/, /fa/imam-javad/admin/, /imam-javad/admin/ + location ~ ^/(en|fa)?/?imam-javad/ { + proxy_pass http://django_backend; + proxy_http_version 1.1; 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; client_max_body_size 1200M; } - # ========== Django Services ========== - - location /api { - proxy_pass http://88.99.212.243:8010; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # ========== 7. Dovoodi Admin Panel (Single Pattern) ========== + # Matches: /en/dovoodi/admin/, /fa/dovoodi/admin/, /dovoodi/admin/ + location ~ ^/(en|fa)?/?dovoodi/ { + proxy_pass http://django_backend; + proxy_http_version 1.1; proxy_set_header Host $host; - proxy_method $request_method; 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; - -<<<<<<< HEAD - # 🔥 CRITICAL: Forward Authorization header for Token authentication -======= ->>>>>>> a1b3ddf (Add Nginx configuration files for dovoodi and imamjavad services) - proxy_set_header Authorization $http_authorization; - proxy_pass_header Authorization; - client_max_body_size 1200M; } - location /en/swagger { - proxy_pass http://88.99.212.243:8010; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # ========== 8. Swagger & API Documentation ========== + # Matches: /en/swagger/, /fa/swagger/, /en/redoc/, /fa/redoc/, /en/docs/ + location ~ ^/(en|fa)/(swagger|redoc|docs) { + proxy_pass http://django_backend; + proxy_http_version 1.1; 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; proxy_set_header Authorization $http_authorization; proxy_pass_header Authorization; } - location /en/redoc { - proxy_pass http://88.99.212.243:8010; - proxy_set_header Authorization $http_authorization; - proxy_pass_header Authorization; - } - - location /i18n/ { - proxy_pass http://88.99.212.243:8010; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $host; - } - - # ========== Other Services ========== - - location /chat { - proxy_pass http://88.99.212.243:8020; - client_max_body_size 1200M; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; + # ========== 9. Filer (Django File Manager) ========== + location /filer/ { + proxy_pass http://django_backend; + proxy_http_version 1.1; 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; + client_max_body_size 1200M; } -<<<<<<< HEAD - location /static/ { - alias /home/app/web/imam_javad_static/static/; - } - - location /media/ { - alias /home/app/web/imam_javad_static/media/; -======= - - location /static/ { - alias /home/app/web/imam_javad_staticfiles/; - expires 30d; - add_header Cache-Control "public, immutable"; - } - - location /media/{ - alias /home/app/web/imam_javad_mediafiles/; - - expires 30d; - add_header Cache-Control "public, immutable"; - - # Enable CORS for media files - add_header Access-Control-Allow-Origin *; - add_header Access-Control-Allow-Methods "GET, OPTIONS"; - add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept"; ->>>>>>> a1b3ddf (Add Nginx configuration files for dovoodi and imamjavad services) + # ========== 10. Admin Entry Point Redirect ========== + # /admin → /en/imam-javad/admin/ + location = /admin { + return 301 /en/imam-javad/admin/; } - - # ========== Next.js Frontend ========== - location /_next/ { - proxy_pass http://88.99.212.243:7226/_next/; - 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; - expires 1y; - add_header Cache-Control "public, immutable"; + location = /admin/ { + return 301 /en/imam-javad/admin/; } -<<<<<<< HEAD - # ⚠️ این باید آخرین location باشد (fallback) -======= ->>>>>>> a1b3ddf (Add Nginx configuration files for dovoodi and imamjavad services) + # ========== 11. Next.js Frontend (Catch-all - Lowest Priority) ========== location / { - proxy_pass http://88.99.212.243:7226; - client_max_body_size 1200M; + proxy_pass http://nextjs_frontend; + proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; 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; } }