mirror of
https://github.com/dartdavros/chatballs.git
synced 2026-10-05 09:14:58 +03:00
- каталог code/custocrm → code/chatballs; CLI custocrm → chatballs; пакеты hub_platform → chatballs, hub_backend → chatballs_backend (app labels прежние) - переменные CUS_* и CUSTOCRM_* → CHATBALLS_*; образы chatballs-*; compose-проект и база chatballs (были edevs_hub); роли Postgres chatballs_* (были custocrm_*); схема RLS chatballs и GUC chatballs.organization_id; cookie chatballs_* - CI: APP_DIR code/chatballs, DEPLOY_ROOT /opt/chatballs - deploy/migrate/rename-to-chatballs.sh — миграция существующей установки без потери данных: остановка старого проекта, .env (с резервной копией), переименование суперпользователя initdb через временную роль, остальных ролей, базы, схемы и функции RLS; проверено на локальном стеке - dev-стек хранит Postgres в bind-mount data/postgres, как prod (именованный том compose.dev был устаревшим снимком и вводил в заблуждение) - снятие демо удаляет объекты, созданные поверх демо-данных тестировавшим (звонки по демо-диалогу), вместо падения на PROTECT - реальные домены *.custocrm.ru и идентификаторы документов не тронуты Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
68 lines
2.7 KiB
Python
68 lines
2.7 KiB
Python
import os
|
|
from pathlib import Path
|
|
|
|
from django.core.exceptions import ImproperlyConfigured
|
|
|
|
|
|
def build_storage_settings(
|
|
*,
|
|
base_dir: Path,
|
|
debug: bool,
|
|
testing: bool,
|
|
) -> tuple[str, Path, dict[str, dict]]:
|
|
backend = os.environ.get(
|
|
"CHATBALLS_STORAGE_BACKEND",
|
|
"filesystem" if debug or testing else "s3",
|
|
).lower()
|
|
if backend not in {"filesystem", "s3"}:
|
|
raise ImproperlyConfigured("CHATBALLS_STORAGE_BACKEND must be 's3' or 'filesystem'")
|
|
if not debug and not testing and backend != "s3":
|
|
raise ImproperlyConfigured("Production tenant storage must use the S3 backend")
|
|
|
|
default_storage: dict = {
|
|
"BACKEND": "chatballs.tenancy.storage_backends.TenantFileSystemStorage",
|
|
}
|
|
# Файлы пользователя (фото профиля) — вне тенантного ограждения: пользователь
|
|
# может состоять в нескольких организациях. Ключи под users/<id>/.
|
|
users_storage: dict = {
|
|
"BACKEND": "chatballs.tenancy.storage_backends.UserFileSystemStorage",
|
|
}
|
|
if backend == "s3":
|
|
bucket_name = os.environ.get("CHATBALLS_S3_BUCKET", "")
|
|
if not bucket_name:
|
|
raise ImproperlyConfigured("CHATBALLS_S3_BUCKET is required for S3 storage")
|
|
s3_options = {
|
|
"bucket_name": bucket_name,
|
|
"endpoint_url": os.environ.get("CHATBALLS_S3_ENDPOINT_URL") or None,
|
|
"region_name": os.environ.get("CHATBALLS_S3_REGION") or None,
|
|
"access_key": os.environ.get("CHATBALLS_S3_ACCESS_KEY") or None,
|
|
"secret_key": os.environ.get("CHATBALLS_S3_SECRET_KEY") or None,
|
|
"addressing_style": os.environ.get("CHATBALLS_S3_ADDRESSING_STYLE", "path"),
|
|
"default_acl": None,
|
|
"file_overwrite": False,
|
|
"querystring_auth": True,
|
|
"querystring_expire": int(
|
|
os.environ.get("CHATBALLS_S3_URL_EXPIRY_SECONDS", "900")
|
|
),
|
|
}
|
|
default_storage = {
|
|
"BACKEND": "chatballs.tenancy.storage_backends.TenantS3Storage",
|
|
"OPTIONS": s3_options,
|
|
}
|
|
users_storage = {
|
|
"BACKEND": "chatballs.tenancy.storage_backends.UserS3Storage",
|
|
"OPTIONS": s3_options,
|
|
}
|
|
|
|
media_root = Path(os.environ.get("CHATBALLS_MEDIA_ROOT", base_dir / "media"))
|
|
storages = {
|
|
"default": default_storage,
|
|
"users": users_storage,
|
|
"staticfiles": {
|
|
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage"
|
|
if testing
|
|
else "whitenoise.storage.CompressedManifestStaticFilesStorage",
|
|
},
|
|
}
|
|
return backend, media_root, storages
|