reverted to old web configuration on main branch
This commit is contained in:
0
vontor_cz/__init__.py
Normal file
0
vontor_cz/__init__.py
Normal file
29
vontor_cz/asgi.py
Normal file
29
vontor_cz/asgi.py
Normal file
@@ -0,0 +1,29 @@
|
||||
"""
|
||||
ASGI config for vontor_cz project.
|
||||
|
||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/
|
||||
"""
|
||||
import os
|
||||
import django
|
||||
|
||||
from django.core.asgi import get_asgi_application
|
||||
from channels.routing import ProtocolTypeRouter, URLRouter
|
||||
from channels.security.websocket import AllowedHostsOriginValidator
|
||||
from channels.auth import AuthMiddlewareStack
|
||||
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'vontor_cz.settings')
|
||||
|
||||
|
||||
application = ProtocolTypeRouter({
|
||||
"http": get_asgi_application(),
|
||||
|
||||
"websocket": AllowedHostsOriginValidator(
|
||||
AuthMiddlewareStack(
|
||||
URLRouter(__import__('home.routing').routing.websocket_urlpatterns)
|
||||
)
|
||||
),
|
||||
})
|
||||
29
vontor_cz/backend.py
Normal file
29
vontor_cz/backend.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from django.contrib.auth.backends import BaseBackend
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
|
||||
class EmailOrUsernameModelBackend(BaseBackend):
|
||||
def authenticate(self, request, username=None, password=None, **kwargs):
|
||||
print('custom backend used')
|
||||
|
||||
UserModel = get_user_model()
|
||||
if '@' in username:
|
||||
# If "@" is present, treat it as an email address
|
||||
try:
|
||||
user = UserModel.objects.get(email=username)
|
||||
except UserModel.DoesNotExist:
|
||||
return None
|
||||
else:
|
||||
# Otherwise, treat it as a username
|
||||
user = UserModel.objects.filter(username=username).first()
|
||||
|
||||
if user and user.check_password(password):
|
||||
return user
|
||||
return None
|
||||
|
||||
def get_user(self, user_id):
|
||||
UserModel = get_user_model()
|
||||
try:
|
||||
return UserModel.objects.get(pk=user_id)
|
||||
except UserModel.DoesNotExist:
|
||||
return None
|
||||
18
vontor_cz/error.py
Normal file
18
vontor_cz/error.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
def error_img_path(codeStatus):
|
||||
img = 'img/errors/' + str(codeStatus) + '.png'
|
||||
return img
|
||||
|
||||
def error_404_view(request, exception=None):
|
||||
codeStatus = 404
|
||||
return render(request, 'error.html',{'codeStatus':codeStatus, 'img': error_img_path(codeStatus)}, status=404)
|
||||
|
||||
|
||||
def error_500_view(request, exception=None):
|
||||
codeStatus = 500
|
||||
return render(request, 'error.html', {'codeStatus':codeStatus, 'img': error_img_path(codeStatus)}, status=500)
|
||||
|
||||
def error_403_view(request, exception=None):
|
||||
codeStatus = 403
|
||||
return render(request, 'error.html',{'codeStatus':codeStatus, 'img': error_img_path(codeStatus)}, status=403)
|
||||
391
vontor_cz/settings.py
Normal file
391
vontor_cz/settings.py
Normal file
@@ -0,0 +1,391 @@
|
||||
"""
|
||||
Django settings for vontor_cz project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 5.1.3.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/5.1/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/5.1/ref/settings/
|
||||
"""
|
||||
import os
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from django.core.management.utils import get_random_secret_key
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from django.db import OperationalError, connections
|
||||
from dotenv import load_dotenv
|
||||
|
||||
|
||||
load_dotenv() # Pouze načte proměnné lokálně, pokud nejsou dostupné
|
||||
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
|
||||
|
||||
SECRET_KEY = os.getenv("DJANGO_SECRET_KEY", "kokotiJsouKokoticozserovna2kokote")
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
if os.getenv("DEBUG", "").lower() in ["true", "1", "yes"]:
|
||||
DEBUG = True
|
||||
else:
|
||||
DEBUG = False
|
||||
|
||||
if os.getenv("SSL", "").lower() in ["true", "1", "yes"]:
|
||||
SSL = True
|
||||
else:
|
||||
SSL = False
|
||||
|
||||
|
||||
|
||||
print(f"DEBUG state: {str(DEBUG)}\nDEBUG .env raw: {os.getenv("DEBUG", "")}")
|
||||
print(f"SSL state: {str(SSL)}\SSL .env raw: {os.getenv("SSL", "")}")
|
||||
|
||||
|
||||
|
||||
ALLOWED_HOSTS = ["www.vontor.cz", "vontor.cz", "https://peerjs.vontor.cz"]
|
||||
CSRF_TRUSTED_ORIGINS = ['https://vontor.cz', "https://www.vontor.cz", "https://peerjs.vontor.cz"]
|
||||
|
||||
if DEBUG:
|
||||
ALLOWED_HOSTS.extend(["localhost", "127.0.0.1"])
|
||||
CSRF_TRUSTED_ORIGINS.extend(["http://localhost:8000"])
|
||||
|
||||
#bezpečnost/SSL
|
||||
if SSL is True:
|
||||
print("SSL turned on!")
|
||||
SESSION_COOKIE_SECURE = True
|
||||
CSRF_COOKIE_SECURE = True
|
||||
SECURE_SSL_REDIRECT = True
|
||||
SECURE_BROWSER_XSS_FILTER = True
|
||||
SECURE_CONTENT_TYPE_NOSNIFF = True
|
||||
USE_X_FORWARDED_HOST = True
|
||||
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
||||
else:
|
||||
SESSION_COOKIE_SECURE = False
|
||||
CSRF_COOKIE_SECURE = False
|
||||
SECURE_SSL_REDIRECT = False
|
||||
SECURE_BROWSER_XSS_FILTER = False
|
||||
SECURE_CONTENT_TYPE_NOSNIFF = False
|
||||
USE_X_FORWARDED_HOST = False
|
||||
|
||||
# Application definition
|
||||
MY_CREATED_APPS = [
|
||||
'api',
|
||||
'home',
|
||||
]
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'daphne', #asgi bude fungovat lokálně (musí být na začátku)
|
||||
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
|
||||
'corsheaders',#cors
|
||||
|
||||
|
||||
#'chat.apps.GlobalChatCheck', #tohle se spusti při každé django inicializaci (migration, createmigration, runserver)
|
||||
|
||||
#'authentication',
|
||||
|
||||
'storages',# Adds support for external storage services like Amazon S3 via django-storages
|
||||
|
||||
'channels' ,# django channels
|
||||
|
||||
'rest_framework',
|
||||
'rest_framework_api_key',
|
||||
|
||||
'django.contrib.sitemaps',
|
||||
|
||||
'tinymce',
|
||||
|
||||
#kvůli bugum je lepší to dát na poslední místo v INSTALLED_APPS
|
||||
'django_cleanup.apps.CleanupConfig', #app která maže nepoužité soubory(media) z databáze na S3
|
||||
]
|
||||
|
||||
INSTALLED_APPS = INSTALLED_APPS[:-1] + MY_CREATED_APPS + INSTALLED_APPS[-1:]
|
||||
|
||||
|
||||
|
||||
|
||||
MIDDLEWARE = [
|
||||
"corsheaders.middleware.CorsMiddleware",# Middleware that allows your backend to accept requests from other domains (CORS)
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
|
||||
#CUSTOM
|
||||
#'tools.middleware.CustomMaxUploadSizeMiddleware',
|
||||
|
||||
|
||||
'whitenoise.middleware.WhiteNoiseMiddleware',# díky tomu funguje načítaní static files
|
||||
]
|
||||
|
||||
# Caching settings for Redis (using Docker's internal network name for Redis)
|
||||
if DEBUG is False:
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.redis.RedisCache',
|
||||
'LOCATION': 'redis://redis:6379/0', # Using the service name `redis` from Docker Compose
|
||||
'OPTIONS': {
|
||||
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
|
||||
'PASSWORD': os.getenv('REDIS_PASSWORD'), # Make sure to set REDIS_PASSWORD in your environment
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
# WebSockets Channel Layers (using Redis in production)
|
||||
CHANNEL_LAYERS = {
|
||||
'default': {
|
||||
'BACKEND': 'channels_redis.core.RedisChannelLayer',
|
||||
'CONFIG': {
|
||||
'hosts': [('redis', 6379)], # Use `redis` service in Docker Compose
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
else:
|
||||
# Use in-memory channel layer for development (when DEBUG is True)
|
||||
CHANNEL_LAYERS = {
|
||||
'default': {
|
||||
'BACKEND': 'channels.layers.InMemoryChannelLayer',
|
||||
}
|
||||
}
|
||||
|
||||
# Use in-memory cache for development (when DEBUG is True)
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ROOT_URLCONF = 'vontor_cz.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
"DIRS": [BASE_DIR / 'templates'],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
ASGI_APPLICATION = 'vontor_cz.asgi.application' #daphne
|
||||
|
||||
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': os.getenv('DATABASE_ENGINE'),
|
||||
'NAME': os.getenv('DATABASE_NAME'),
|
||||
'USER': os.getenv('DATABASE_USER'),
|
||||
'PASSWORD': os.getenv('DATABASE_PASSWORD'),
|
||||
'HOST': os.getenv('DATABASE_HOST'),
|
||||
'PORT': os.getenv('DATABASE_PORT'),
|
||||
}
|
||||
}
|
||||
|
||||
#DATABASE HEALTCHECK
|
||||
try:
|
||||
# Check if the default database connection is working
|
||||
connection = connections['default']
|
||||
|
||||
print("-------------------------\nDatabase host: " + os.getenv('DATABASE_HOST'))
|
||||
print(connection)
|
||||
|
||||
connection.ensure_connection()
|
||||
print("Database connection is successful.")
|
||||
except OperationalError:
|
||||
print("Database connection failed!")
|
||||
raise Exception("Database connection not available, shutting down!")
|
||||
|
||||
print("-------------------------")
|
||||
|
||||
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': [
|
||||
'rest_framework.authentication.SessionAuthentication', # For admin or user auth
|
||||
'rest_framework_api_key.permissions.HasAPIKey', # For API key auth
|
||||
],
|
||||
'DEFAULT_PERMISSION_CLASSES': [
|
||||
'rest_framework.permissions.AllowAny', # Public access by default
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' #SMTP
|
||||
EMAIL_HOST = os.getenv("EMAIL_HOST")
|
||||
EMAIL_PORT = 465
|
||||
EMAIL_USE_TLS = True
|
||||
EMAIL_USE_SSL = False
|
||||
EMAIL_HOST_USER = os.getenv("EMAIL_USER")
|
||||
EMAIL_HOST_PASSWORD = os.getenv("EMAIL_USER_PASSWORD")
|
||||
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER # Optional, if you want a default sender
|
||||
EMAIL_TIMEOUT = 20
|
||||
|
||||
|
||||
#AUTH_USER_MODEL = 'api.User'
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/4.2/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',
|
||||
},
|
||||
]
|
||||
|
||||
AUTHENTICATION_BACKENDS = [
|
||||
'vontor_cz.backend.EmailOrUsernameModelBackend', #custom backend z authentication aplikace
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
]
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/4.2/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
TIME_ZONE = 'Europe/Prague'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
||||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
|
||||
SESSION_COOKIE_AGE = 86400 # one day
|
||||
|
||||
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
|
||||
|
||||
LOGIN_URL = 'login'
|
||||
|
||||
|
||||
#---------------------MEDIA + STATIC, AWS--------------------------
|
||||
|
||||
# Static files directories
|
||||
STATICFILES_DIRS = [
|
||||
BASE_DIR / 'globalstaticfiles',
|
||||
]
|
||||
|
||||
# Include app-specific static files (excluding certain apps like django or rest_framework)
|
||||
for app in settings.INSTALLED_APPS:
|
||||
if app.startswith('django.') or 'rest_framework' in app or '.' in app:
|
||||
continue
|
||||
app_path = Path(BASE_DIR, app.replace('.', '/'))
|
||||
static_path = app_path / 'static'
|
||||
if static_path.exists():
|
||||
STATICFILES_DIRS.append(static_path)
|
||||
|
||||
# Production / Development settings
|
||||
if DEBUG:
|
||||
# Development: Use local file system storage for static files
|
||||
STORAGES = {
|
||||
"default": {
|
||||
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
||||
},
|
||||
"staticfiles": {
|
||||
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
|
||||
},
|
||||
}
|
||||
|
||||
# Media and Static URL for local dev
|
||||
MEDIA_URL = '/media/'
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
# Local folder for collected static files
|
||||
STATIC_ROOT = BASE_DIR / 'collectedstaticfiles'
|
||||
|
||||
elif DEBUG is False:
|
||||
AWS_LOCATION = "static"
|
||||
|
||||
# Production: Use S3 storage
|
||||
STORAGES = {
|
||||
"default": {
|
||||
"BACKEND" : "storages.backends.s3boto3.S3StaticStorage",
|
||||
},
|
||||
|
||||
"staticfiles": {
|
||||
"BACKEND" : "storages.backends.s3boto3.S3StaticStorage",
|
||||
},
|
||||
}
|
||||
|
||||
# Media and Static URL for AWS S3
|
||||
MEDIA_URL = f'https://{os.getenv("AWS_STORAGE_BUCKET_NAME")}.s3.amazonaws.com/media/'
|
||||
STATIC_URL = f'https://{os.getenv("AWS_STORAGE_BUCKET_NAME")}.s3.amazonaws.com/static/'
|
||||
|
||||
# Static files should be collected to a local directory and then uploaded to S3
|
||||
STATIC_ROOT = BASE_DIR / 'collectedstaticfiles'
|
||||
|
||||
AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID')
|
||||
AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY')
|
||||
AWS_STORAGE_BUCKET_NAME = os.getenv('AWS_STORAGE_BUCKET_NAME')
|
||||
AWS_S3_REGION_NAME = os.getenv('AWS_S3_REGION_NAME', 'us-east-1') # Default to 'us-east-1' if not set
|
||||
AWS_S3_SIGNATURE_VERSION = 's3v4' # Use AWS Signature Version 4
|
||||
AWS_S3_USE_SSL = True
|
||||
AWS_S3_FILE_OVERWRITE = True
|
||||
AWS_DEFAULT_ACL = None # Set to None to avoid setting a default ACL
|
||||
|
||||
|
||||
|
||||
|
||||
print(f"Static url: {STATIC_URL}\nStatic storage:{STORAGES}\n.............")
|
||||
|
||||
#--------------------END-MEDIA-STATIC-SECTION------------------
|
||||
|
||||
TINYMCE_JS_URL = 'https://cdn.tiny.cloud/1/no-api-key/tinymce/7/tinymce.min.js'
|
||||
|
||||
TINYMCE_DEFAULT_CONFIG = {
|
||||
"height": "320px",
|
||||
"width": "960px",
|
||||
"menubar": "file edit view insert format tools table help",
|
||||
"plugins": "advlist autolink lists link image charmap print preview anchor searchreplace visualblocks code "
|
||||
"fullscreen insertdatetime media table paste code help wordcount spellchecker",
|
||||
"toolbar": "undo redo | bold italic underline strikethrough | fontselect fontsizeselect formatselect | alignleft "
|
||||
"aligncenter alignright alignjustify | outdent indent | numlist bullist checklist | forecolor "
|
||||
"backcolor casechange permanentpen formatpainter removeformat | pagebreak | charmap emoticons | "
|
||||
"fullscreen preview save print | insertfile image media pageembed template link anchor codesample | "
|
||||
"a11ycheck ltr rtl | showcomments addcomment code",
|
||||
"custom_undo_redo_levels": 10,
|
||||
}
|
||||
TINYMCE_SPELLCHECKER = True
|
||||
TINYMCE_COMPRESSOR = True
|
||||
30
vontor_cz/urls.py
Normal file
30
vontor_cz/urls.py
Normal file
@@ -0,0 +1,30 @@
|
||||
"""
|
||||
URL configuration for vontor_cz project.
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/5.1/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from django.views.generic import RedirectView
|
||||
from django.conf import settings
|
||||
from django.conf.urls.static import static
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('', include('home.urls')),
|
||||
path('api/', include('api.urls')),
|
||||
path("ads.txt", RedirectView.as_view(url=settings.STATIC_URL + "ads.txt", permanent=True)),
|
||||
|
||||
path('tinymce/', include('tinymce.urls')),
|
||||
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||
24
vontor_cz/validators.py
Normal file
24
vontor_cz/validators.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
def file_size(value, limit): # add this to some file where you can import it from
|
||||
'''
|
||||
---
|
||||
do `limit` napiš počet MegaBajtu!
|
||||
---
|
||||
|
||||
'''
|
||||
calculated_limit = limit * 1024 * 1024
|
||||
|
||||
if value.size > calculated_limit:
|
||||
raise ValidationError('File too large. Size should not exceed ' + str(limit) + ' MiB.')
|
||||
|
||||
def photo_extension(value):
|
||||
'''
|
||||
ověření přípon souboru které funguji s html
|
||||
'''
|
||||
import os
|
||||
from django.core.exceptions import ValidationError
|
||||
ext = os.path.splitext(value.name)[1] # [0] returns path+filename
|
||||
valid_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.apng' , '.avif', '.svg', '.webp']
|
||||
if not ext.lower() in valid_extensions:
|
||||
raise ValidationError('Unsupported image file.')
|
||||
16
vontor_cz/wsgi.py
Normal file
16
vontor_cz/wsgi.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
WSGI config for vontor_cz project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'vontor_cz.settings')
|
||||
|
||||
application = get_wsgi_application()
|
||||
Reference in New Issue
Block a user