gukgjzkgjhgjh

This commit is contained in:
2026-04-20 00:04:15 +02:00
parent 5280a87e8b
commit 659999f4fd
409 changed files with 19957 additions and 5176 deletions

View File

@@ -11,15 +11,15 @@ import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
#import myapp.routing # your app's routing
import social.chat.routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'vontor_cz.settings')
application = ProtocolTypeRouter({
"http": get_asgi_application(),
# "websocket": AuthMiddlewareStack(
# URLRouter(
# #myapp.routing.websocket_urlpatterns
# )
# ),
"websocket": AuthMiddlewareStack(
URLRouter(
social.chat.routing.websocket_urlpatterns
)
),
})

View File

@@ -1,4 +1,7 @@
import os
import math
import hashlib
import base64
from io import BytesIO
from PIL import Image
from django.db import models
@@ -8,44 +11,112 @@ import logging
logger = logging.getLogger(__name__)
class WebPImageField(models.ImageField):
def _get_fernet():
"""
A custom ImageField that converts uploaded images to WebP automatically.
Returns a Fernet (or MultiFernet) instance for encryption/decryption.
Inherits from models.ImageField (description: "Image").
Accepts the same arguments:
verbose_name, name, upload_to, storage,
width_field, height_field, **kwargs
Settings:
FIELD_ENCRYPTION_KEY — single key (str or bytes), or a list of keys for rotation.
First key in a list is used for new encrypts; all are tried
for decrypts, so old values remain readable after a key change.
Falls back to a SECRET_KEY-derived key when not set (development only).
Key rotation workflow:
1. Add new key as the FIRST item in FIELD_ENCRYPTION_KEY list.
2. Keep old key(s) as remaining items — old values still decrypt fine.
3. Optionally run a migration command to re-encrypt all rows with the new key,
then remove old keys from the list.
"""
from cryptography.fernet import Fernet, MultiFernet
from django.conf import settings
raw_setting = getattr(settings, 'FIELD_ENCRYPTION_KEY', None)
if isinstance(raw_setting, (str, bytes)):
# Single key
key = raw_setting.encode() if isinstance(raw_setting, str) else raw_setting
return Fernet(key)
# List of keys — first is active, rest are for decrypting old values
fernet_keys = [
Fernet(k.encode() if isinstance(k, str) else k)
for k in raw_setting
]
return MultiFernet(fernet_keys)
class WebPImageField(models.ImageField):
"""Converts uploaded images to WebP on save. Drop-in replacement for ImageField."""
def pre_save(self, model_instance, add):
file_obj = getattr(model_instance, self.attname)
uploaded_file = getattr(model_instance, self.attname)
if file_obj and not file_obj._committed:
self._convert_to_webp(file_obj)
if uploaded_file and not uploaded_file._committed:
self._convert_to_webp(uploaded_file)
return super().pre_save(model_instance, add)
def _convert_to_webp(self, file_obj):
def _convert_to_webp(self, uploaded_file):
try:
file_obj.open()
image = Image.open(file_obj)
uploaded_file.open()
image = Image.open(uploaded_file)
if image.format == 'WEBP':
image.close()
return
# Preserve transparency for palette/alpha modes
if image.mode == 'P':
image = image.convert('RGBA')
elif image.mode not in ('RGBA', 'LA'):
image = image.convert('RGB')
image_io = BytesIO()
image.save(image_io, format='WEBP', quality=85, optimize=True)
webp_buffer = BytesIO()
image.save(webp_buffer, format='WEBP', quality=100, optimize=True)
image.close()
new_filename = os.path.splitext(file_obj.name)[0] + '.webp'
file_obj.save(new_filename, ContentFile(image_io.getvalue()), save=False)
webp_filename = os.path.splitext(uploaded_file.name)[0] + '.webp'
uploaded_file.save(webp_filename, ContentFile(webp_buffer.getvalue()), save=False)
except Exception as e:
logger.error(f"WebP conversion failed: {e}")
except Exception as error:
logger.error(f"WebP conversion failed: {error}")
class EncryptedCharField(models.CharField):
"""
Transparently encrypts values at rest using Fernet (AES-128-CBC + HMAC-SHA256).
Drop-in replacement for CharField — max_length is the plaintext limit.
Set FIELD_ENCRYPTION_KEY in settings to a URL-safe base64 32-byte key
(generate: from cryptography.fernet import Fernet; Fernet.generate_key()).
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# DB column must fit the Fernet token: plaintext + 73 bytes overhead, base64-encoded
plaintext_max_length = self.max_length or 200
self._db_column_max_length = math.ceil((plaintext_max_length + 73) / 3) * 4
def db_type(self, connection):
# Silently use the larger column size; migrations still show plaintext max_length
return connection.data_types['CharField'] % {'max_length': self._db_column_max_length}
def from_db_value(self, value, expression, connection):
if not value:
return value
try:
return _get_fernet().decrypt(value.encode()).decode()
except Exception:
logger.warning("EncryptedCharField: decryption failed, returning raw value.")
return value
def get_prep_value(self, value):
if value is None or value == '':
return super().get_prep_value(value)
return _get_fernet().encrypt(value.encode()).decode()
def to_python(self, value):
if value is None:
return value
return str(value)

View File

@@ -348,6 +348,8 @@ MY_CREATED_APPS = [
'configuration',
'social.chat',
'social.hubs',
'social.posts',
'advertisement',

View File

@@ -19,7 +19,7 @@ from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings
from django import settings
from django.conf import settings
from .views import choices
from drf_spectacular.views import (
@@ -43,6 +43,10 @@ urlpatterns = [
path('api/configuration/', include('configuration.urls')),
path('api/advertisement/', include('advertisement.urls')),
path('api/social/hubs/', include('social.hubs.urls')),
path('api/social/posts/', include('social.posts.urls')),
path('api/social/', include('social.chat.urls')),
path('api/stripe/', include('thirdparty.stripe.urls')),
path('api/trading212/', include('thirdparty.trading212.urls')),
path('api/downloader/', include('thirdparty.downloader.urls')),