diff --git a/registrar/apps/core/filestore.py b/registrar/apps/core/filestore.py index 206616c9..8630cf2a 100644 --- a/registrar/apps/core/filestore.py +++ b/registrar/apps/core/filestore.py @@ -7,7 +7,8 @@ from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.core.files.base import ContentFile -from django.core.files.storage import default_storage, get_storage_class +from django.core.files.storage import default_storage +from django.utils.module_loading import import_string from registrar.apps.api.utils import to_absolute_api_url @@ -15,6 +16,22 @@ logger = logging.getLogger(__name__) +def get_storage_class(): + # Prefer new-style Django 4.2+ STORAGES + storages_config = getattr(settings, 'STORAGES', {}) + + if storages_config.get('default') and storages_config['default'].get('BACKEND'): + return import_string(storages_config['default'].get('BACKEND')) + + # Legacy fallback: DEFAULT_FILE_STORAGE + storage_class_path = getattr(settings, 'DEFAULT_FILE_STORAGE', {}) + + if storage_class_path: + return import_string(storage_class_path) + + return default_storage.__class__ + + class FilestoreBase: """ Abstract base class for file stores. diff --git a/registrar/apps/core/tests/test_filestore.py b/registrar/apps/core/tests/test_filestore.py index 2ca15249..9d492e59 100644 --- a/registrar/apps/core/tests/test_filestore.py +++ b/registrar/apps/core/tests/test_filestore.py @@ -9,7 +9,10 @@ import moto import requests from botocore.exceptions import ClientError +from django.conf import settings from django.test import TestCase +from django.test.utils import override_settings +from storages.backends.s3boto3 import S3Boto3Storage from ..filestore import ( FilestoreBase, @@ -19,6 +22,7 @@ get_filestore, get_job_results_filestore, get_program_reports_filestore, + get_storage_class, ) from ..filestore import logger as filestore_logger from .mixins import S3MockEnvVarsMixin @@ -140,3 +144,21 @@ def test_filestore_error_logging(self): assert path_prefix in log_message assert filepath in log_message assert contents not in log_message + + +class GetStorageClassTests(TestCase): + @override_settings( + STORAGES={"default": {"BACKEND": "storages.backends.s3boto3.S3Boto3Storage"}} + ) + def test_get_storage_class_with_storages(self): + storage_class = get_storage_class() + self.assertIs(storage_class, S3Boto3Storage) + + @override_settings( + DEFAULT_FILE_STORAGE="storages.backends.s3boto3.S3Boto3Storage", + STORAGES={} + ) + def test_get_storage_class_with_default_file_storage(self): + del settings.STORAGES + storage_class = get_storage_class() + self.assertIs(storage_class, S3Boto3Storage) diff --git a/registrar/settings/base.py b/registrar/settings/base.py index bf24bf80..ff4c2fb4 100644 --- a/registrar/settings/base.py +++ b/registrar/settings/base.py @@ -189,10 +189,18 @@ root('conf', 'locale'), ) +STORAGES = { + "default": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, + "staticfiles": { + "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage", + }, +} + # MEDIA CONFIGURATION MEDIA_ROOT = root('media') MEDIA_URL = '/api/media/' -DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' REGISTRAR_BUCKET = 'change-me-to-registrar-bucket' PROGRAM_REPORTS_BUCKET = 'change-me-to-program-reports-bucket' PROGRAM_REPORTS_FOLDER = 'reports_v2' @@ -325,7 +333,6 @@ EXTRA_APPS = [] SERVICE_USER = 'registrar_service_user' SESSION_EXPIRE_AT_BROWSER_CLOSE = False -STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage' CSRF_TRUSTED_ORIGINS = [] CACHES = { 'default': { diff --git a/registrar/settings/devstack.py b/registrar/settings/devstack.py index df0b6c0c..3b019141 100644 --- a/registrar/settings/devstack.py +++ b/registrar/settings/devstack.py @@ -35,7 +35,11 @@ } } -STATICFILES_STORAGE = os.environ.get('STATICFILES_STORAGE', 'django.contrib.staticfiles.storage.StaticFilesStorage') +staticfiles_storage = os.environ.get('STATICFILES_STORAGE') + +if staticfiles_storage: + STORAGES["staticfiles"]["BACKEND"] = staticfiles_storage + STATIC_URL = os.environ.get('STATIC_URL', '/static/') LMS_BASE_URL = 'http://edx.devstack.lms:18000' diff --git a/registrar/settings/production.py b/registrar/settings/production.py index 3ac51fa2..bffb3b9b 100644 --- a/registrar/settings/production.py +++ b/registrar/settings/production.py @@ -32,6 +32,15 @@ vars()[key].update(value) vars().update(config_from_yaml) + + default_file_storage = MEDIA_STORAGE_BACKEND.pop('DEFAULT_FILE_STORAGE', None) + staticfiles_storage = MEDIA_STORAGE_BACKEND.pop('STATICFILES_STORAGE', None) + + if default_file_storage: + STORAGES["default"]["BACKEND"] = default_file_storage + if staticfiles_storage: + STORAGES["staticfiles"]["BACKEND"] = staticfiles_storage + vars().update(MEDIA_STORAGE_BACKEND) DB_OVERRIDES = dict( diff --git a/registrar/settings/test.py b/registrar/settings/test.py index c91e5fb6..20b5d9f1 100644 --- a/registrar/settings/test.py +++ b/registrar/settings/test.py @@ -45,7 +45,7 @@ # END CELERY # Media -DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' +STORAGES["default"]["BACKEND"] = 'storages.backends.s3boto3.S3Boto3Storage' AWS_LOCATION = '' AWS_QUERYSTRING_AUTH = True AWS_QUERYSTRING_EXPIRE = 3600