Files
atabackend/core/settings.py
Beyhan Oğur d50f14bcb1 first commit
2026-04-26 22:20:45 +03:00

453 lines
16 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Django settings for core project.
Generated by 'django-admin startproject' using Django 6.0.
For more information on this file, see
https://docs.djangoproject.com/en/6.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/6.0/ref/settings/
"""
from pathlib import Path
import os
import environ
BASE_DIR = Path(__file__).resolve().parent.parent
env = environ.Env()
environ.Env.read_env(os.path.join(BASE_DIR, '.env'))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY', default='django-insecure-slih+3-7gn0b04-2wm4zq)rp*kz1jnt&bf9o3i3*8jhz*n9=2k')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env.bool('DEBUG', default=True)
ALLOWED_HOSTS = ['api.denizogur.com.tr', 'localhost', '127.0.0.1', '[::1]']
CSRF_TRUSTED_ORIGINS = ['https://api.denizogur.com.tr', 'https://*.denizogur.com.tr']
CSRF_COOKIE_DOMAIN = '.denizogur.com.tr'
# Site URL - .env dosyasından alınır
SITE_URL = os.getenv('SITE_URL', 'http://127.0.0.1:8000')
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 3. Parti
'rest_framework',
'rest_framework_simplejwt',
'django_celery_results',
# celery -A [project-name] worker --beat --scheduler django --loglevel=info
'django_celery_beat',
'djoser',
'corsheaders',
'social_django',
'imagekit',
'django_cleanup',
'colorfield',
'autoslug',
'tinymce',
'django.contrib.sites', # Added for Djoser domain resolution
# Local Apps
# 'blog',
'accounts',
'settings',
'backup',
'home',
'portfolio',
'contact',
]
SITE_ID = 1
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
"whitenoise.middleware.WhiteNoiseMiddleware",
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'accounts.middleware.SocialAuthExceptionMiddleware',
]
ROOT_URLCONF = 'core.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates']
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
# Social auth context processors
'social_django.context_processors.backends',
'social_django.context_processors.login_redirect',
],
},
},
]
WSGI_APPLICATION = 'core.wsgi.application'
# Database
# https://docs.djangoproject.com/en/6.0/ref/settings/#databases
# Docker ortamında veya environment değişkeni varsa PostgreSQL kullan
USE_POSTGRES = env.bool('USE_POSTGRES', default=True)
if USE_POSTGRES:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': env('POSTGRES_DB', default='beyhan_blog'),
'USER': env('POSTGRES_USER', default='beyhan_blog'),
'PASSWORD': env('POSTGRES_PASSWORD', default='1923btO**'),
'HOST': env('POSTGRES_HOST', default='212.64.215.243'),
'PORT': env('POSTGRES_PORT', default='5432'),
'OPTIONS': {
'options': '-c search_path=public'
},
}
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# ==============================================================================
# REDIS CACHE CONFIGURATION
# ==============================================================================
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
# 'LOCATION': 'redis://default:1923btO**@ares-redis-xrot7z:6379',
'LOCATION': os.getenv('CELERY_BROKER_URL', 'redis://default:8KNa2T3ceGkrYPpt@212.64.215.243:6379/3'),
# 'LOCATION': os.getenv('REDIS_URL', 'redis://127.0.0.1:6379/1'),
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
},
'KEY_PREFIX': 'ata_',
'TIMEOUT': 300, # 5 dakika default timeout
}
}
# ==============================================================================
# CELERY CONFIGURATION
# ==============================================================================
# CELERY_BROKER_URL = 'redis://default:1923btO**@10.80.80.70:6379/5'
CELERY_BROKER_URL = os.getenv('CELERY_BROKER_URL', 'redis://default:8KNa2T3ceGkrYPpt@212.64.215.243:6379/5')
CELERY_RESULT_BACKEND = os.getenv('CELERY_RESULT_BACKEND', 'django-db')
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Europe/Istanbul' # Türkiye timezone
CELERY_ENABLE_UTC = True # UTC zaman kullan
# Password validation
# https://docs.djangoproject.com/en/6.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/6.0/topics/i18n/
LANGUAGE_CODE = 'tr'
TIME_ZONE = 'Europe/Istanbul'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/6.0/howto/static-files/
STATIC_URL = 'static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATICFILES_DIRS = [
BASE_DIR / 'static',
]
# Media files (User uploaded files)
MEDIA_URL = 'media/'
MEDIA_ROOT = BASE_DIR / 'media'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
# Default primary key field type
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# ==============================================================================
# CUSTOM USER MODEL
# ==============================================================================
AUTH_USER_MODEL = 'accounts.CustomUser'
# ==============================================================================
# REST FRAMEWORK CONFIGURATION
# ==============================================================================
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
'rest_framework.authentication.SessionAuthentication', # For social auth
),
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
# Throttling for security - api.denizogur.com.tr için bypass edildi
'DEFAULT_THROTTLE_CLASSES': [
'core.throttling.CustomAnonRateThrottle',
'core.throttling.CustomUserRateThrottle',
],
'DEFAULT_THROTTLE_RATES': {
'anon': '100/hour', # Anonymous users
'user': '1000/hour', # Authenticated users
},
}
# ==============================================================================
# SIMPLE JWT CONFIGURATION
# ==============================================================================
from datetime import timedelta
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(days=30),
'REFRESH_TOKEN_LIFETIME': timedelta(days=120),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
'UPDATE_LAST_LOGIN': True,
'ALGORITHM': 'HS256',
'SIGNING_KEY': SECRET_KEY,
'VERIFYING_KEY': None,
'AUDIENCE': None,
'ISSUER': None,
'AUTH_HEADER_TYPES': ('Bearer',),
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
'JTI_CLAIM': 'jti',
}
# ==============================================================================
# DJOSER CONFIGURATION
# ==============================================================================
DJOSER = {
# Domain for email links (YOUR FRONTEND URL)
# Djoser combines DOMAIN + ACTIVATION_URL to create the full link
'DOMAIN': 'localhost:3000', # IMPORTANT: Change this to your frontend's domain
'SITE_NAME': 'Django Auth API',
# Registration & Activation
'SEND_ACTIVATION_EMAIL': True,
'ACTIVATION_URL': 'activate/{uid}/{token}', # Frontend route, e.g., http://localhost:3000/activate/MQ/token/
# Password Reset
'SEND_CONFIRMATION_EMAIL': True,
'PASSWORD_RESET_CONFIRM_URL': 'password-reset/{uid}/{token}', # Frontend route
'PASSWORD_RESET_SHOW_EMAIL_NOT_FOUND': False,
# Username Reset
'USERNAME_RESET_CONFIRM_URL': 'username-reset/{uid}/{token}', # Frontend route
# Email confirmations
'PASSWORD_CHANGED_EMAIL_CONFIRMATION': True,
'USERNAME_CHANGED_EMAIL_CONFIRMATION': True,
# User settings
'USER_CREATE_PASSWORD_RETYPE': True,
'SET_PASSWORD_RETYPE': True,
'PASSWORD_RESET_CONFIRM_RETYPE': True,
'LOGIN_FIELD': 'email',
# Serializers
'SERIALIZERS': {
'user_create': 'accounts.serializers.CustomUserCreateSerializer',
'user': 'accounts.serializers.CustomUserSerializer',
'current_user': 'accounts.serializers.CustomUserSerializer',
},
}
# ==============================================================================
# EMAIL CONFIGURATION
# ==============================================================================
# Development: Using MailPit (local email testing tool)
# MailPit default runs on localhost:1025 for SMTP and localhost:8025 for web UI
# SITE_URL = os.getenv('SITE_URL', 'http://127.0.0.1:8000')
EMAIL_BACKEND = os.getenv('EMAIL_BACKEND','django.core.mail.backends.smtp.EmailBackend')
EMAIL_HOST = os.getenv('EMAIL_HOST','212.64.215.243')
EMAIL_PORT = os.getenv('EMAIL_PORT',1025)
# EMAIL_USE_TLS = os.getenv('EMAIL_USE_TLS',False)
# EMAIL_USE_SSL = os.getenv('EMAIL_USE_SSL',True)
EMAIL_HOST_USER = os.getenv('EMAIL_HOST_USER','')
EMAIL_HOST_PASSWORD = os.getenv('EMAIL_HOST_PASSWORD','')
DEFAULT_FROM_EMAIL = os.getenv('DEFAULT_FROM_EMAIL','noreply@localhost')
# Production: Uncomment and configure these with environment variables
# EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
# EMAIL_HOST = os.environ.get('EMAIL_HOST', 'smtp.gmail.com')
# EMAIL_PORT = int(os.environ.get('EMAIL_PORT', 587))
# EMAIL_USE_TLS = os.environ.get('EMAIL_USE_TLS', 'True') == 'True'
# EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')
# EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')
# DEFAULT_FROM_EMAIL = os.environ.get('DEFAULT_FROM_EMAIL', 'noreply@yourdomain.com')
# ==============================================================================
# CORS CONFIGURATION
# ==============================================================================
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000", # Next.js default
"http://127.0.0.1:3000",
"http://localhost:5173", # Vite default
"http://127.0.0.1:5173",
"http://localhost:8080", # Vue/Nuxt alternative port
"http://127.0.0.1:8080",
]
# For development only - be careful in production!
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_HEADERS = [
'accept',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
]
# ==============================================================================
# SOCIAL AUTH CONFIGURATION (Python Social Auth)
# ==============================================================================
AUTHENTICATION_BACKENDS = (
# Social auth backends
'social_core.backends.google.GoogleOAuth2',
'social_core.backends.github.GithubOAuth2',
'social_core.backends.facebook.FacebookOAuth2',
# Add more providers as needed
# Django default
'django.contrib.auth.backends.ModelBackend',
)
# Social Auth Settings
SOCIAL_AUTH_JSONFIELD_ENABLED = True
SOCIAL_AUTH_URL_NAMESPACE = 'social'
# Pipeline - custom pipeline to set is_active=True for social users
SOCIAL_AUTH_PIPELINE = (
'social_core.pipeline.social_auth.social_details',
'social_core.pipeline.social_auth.social_uid',
'social_core.pipeline.social_auth.auth_allowed',
'social_core.pipeline.social_auth.social_user',
'social_core.pipeline.user.get_username',
'social_core.pipeline.user.create_user',
'social_core.pipeline.social_auth.associate_user',
'social_core.pipeline.social_auth.load_extra_data',
'social_core.pipeline.user.user_details',
'accounts.pipeline.activate_user', # Custom pipeline to set is_active=True
)
# User model
SOCIAL_AUTH_USER_MODEL = 'accounts.CustomUser'
SOCIAL_AUTH_USERNAME_IS_REQUIRED = False
SOCIAL_AUTH_USER_FIELDS = ['email', 'first_name', 'last_name']
# Strategy
SOCIAL_AUTH_STRATEGY = 'social_django.strategy.DjangoStrategy'
SOCIAL_AUTH_STORAGE = 'social_django.models.DjangoStorage'
# Google OAuth2 Configuration
# Get credentials from: https://console.developers.google.com/
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '915364976256-691m0s87as2r5vdbqr96f6humblseobt.apps.googleusercontent.com' # Your Google Client ID
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = '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' # Your Google Client Secret
SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
]
SOCIAL_AUTH_GOOGLE_OAUTH2_EXTRA_DATA = ['first_name', 'last_name']
# GitHub OAuth2 Configuration
# Get credentials from: https://github.com/settings/developers
SOCIAL_AUTH_GITHUB_KEY = 'Ov23liUt9B61O46Mdfm4' # Your GitHub Client ID
SOCIAL_AUTH_GITHUB_SECRET = 'c7fc8dcb1b2c8f22120608425d07d5efd995baaf' # Your GitHub Client Secret
SOCIAL_AUTH_GITHUB_SCOPE = ['user:email']
# Facebook OAuth2 Configuration
# Get credentials from: https://developers.facebook.com/
SOCIAL_AUTH_FACEBOOK_KEY = '' # Your Facebook App ID
SOCIAL_AUTH_FACEBOOK_SECRET = '' # Your Facebook App Secret
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']
SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {
'fields': 'id, name, email, first_name, last_name'
}
# Redirect URLs (customize for your frontend)
LOGIN_URL = '/api/v1/spa/'
LOGIN_REDIRECT_URL = '/api/v1/auth/social/callback/'
SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/api/v1/auth/social/callback/'
SOCIAL_AUTH_NEW_USER_REDIRECT_URL = '/api/v1/auth/social/callback/'
SOCIAL_AUTH_INACTIVE_USER_URL = '/api/v1/auth/social/error/'
SOCIAL_AUTH_LOGIN_ERROR_URL = '/api/v1/auth/social/error/'
TASKS = {"default": {"BACKEND": "django.tasks.backends.immediate.ImmediateBackend"}}
# ==============================================================================
# SECURITY SETTINGS FOR SPA/JWT
# ==============================================================================
# Since we're using JWT tokens (not session cookies), we can relax CSRF for API endpoints
# But keep it enabled for Django admin
"""
CSRF_COOKIE_HTTPONLY = False
CSRF_COOKIE_SECURE = False # Set to True in production with HTTPS
SESSION_COOKIE_SECURE = False # Set to True in production with HTTPS
CSRF_TRUSTED_ORIGINS = [
"http://localhost:3000",
"http://localhost:5173",
]
"""