From f8e60f4a897e5a9fad110ba534d31653f420eb31 Mon Sep 17 00:00:00 2001 From: Chris Moultrie <821688+tebriel@users.noreply.github.com> Date: Sun, 5 Mar 2023 10:05:20 -0500 Subject: [PATCH] Enable Azure BlobStorage as an alternative to AWS S3 This adds a new storage backend for Azure BlobStorage, I'm running this patch in Azure Kubernetes hosting all my assets in Azure BlobStorage and it's been stable enough I thought I should commit this back upstream. --- .dockerignore | 1 + bookwyrm/settings.py | 18 ++++++++++++++++++ bookwyrm/storage_backends.py | 14 ++++++++++++++ requirements.txt | 1 + 4 files changed, 34 insertions(+) diff --git a/.dockerignore b/.dockerignore index a5130c8bd..5edf3de0d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -5,3 +5,4 @@ __pycache__ .git .github .pytest* +.env diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index bf0467ebc..b94d86615 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -341,6 +341,7 @@ if USE_HTTPS: CSRF_COOKIE_SECURE = True USE_S3 = env.bool("USE_S3", False) +USE_AZURE = env.bool("USE_AZURE", False) if USE_S3: # AWS settings @@ -364,6 +365,23 @@ if USE_S3: DEFAULT_FILE_STORAGE = "bookwyrm.storage_backends.ImagesStorage" CSP_DEFAULT_SRC = ["'self'", AWS_S3_CUSTOM_DOMAIN] + CSP_ADDITIONAL_HOSTS CSP_SCRIPT_SRC = ["'self'", AWS_S3_CUSTOM_DOMAIN] + CSP_ADDITIONAL_HOSTS +elif USE_AZURE: + AZURE_ACCOUNT_NAME = env("AZURE_ACCOUNT_NAME") + AZURE_ACCOUNT_KEY = env("AZURE_ACCOUNT_KEY") + AZURE_CONTAINER = env("AZURE_CONTAINER") + AZURE_CUSTOM_DOMAIN = env("AZURE_CUSTOM_DOMAIN") + # Azure Static settings + STATIC_LOCATION = "static" + STATIC_URL = f"{PROTOCOL}://{AZURE_CUSTOM_DOMAIN}/{AZURE_CONTAINER}/{STATIC_LOCATION}/" + STATICFILES_STORAGE = "bookwyrm.storage_backends.AzureStaticStorage" + # Azure Media settings + MEDIA_LOCATION = "images" + MEDIA_URL = f"{PROTOCOL}://{AZURE_CUSTOM_DOMAIN}/{AZURE_CONTAINER}/{MEDIA_LOCATION}/" + MEDIA_FULL_URL = MEDIA_URL + STATIC_FULL_URL = STATIC_URL + DEFAULT_FILE_STORAGE = "bookwyrm.storage_backends.AzureImagesStorage" + CSP_DEFAULT_SRC = ["'self'", AZURE_CUSTOM_DOMAIN] + CSP_ADDITIONAL_HOSTS + CSP_SCRIPT_SRC = ["'self'", AZURE_CUSTOM_DOMAIN] + CSP_ADDITIONAL_HOSTS else: STATIC_URL = "/static/" MEDIA_URL = "/images/" diff --git a/bookwyrm/storage_backends.py b/bookwyrm/storage_backends.py index 4fb0feff0..6dd9f522c 100644 --- a/bookwyrm/storage_backends.py +++ b/bookwyrm/storage_backends.py @@ -2,6 +2,7 @@ import os from tempfile import SpooledTemporaryFile from storages.backends.s3boto3 import S3Boto3Storage +from storages.backends.azure_storage import AzureStorage class StaticStorage(S3Boto3Storage): # pylint: disable=abstract-method @@ -47,3 +48,16 @@ class ImagesStorage(S3Boto3Storage): # pylint: disable=abstract-method # Upload the object which will auto close the # content_autoclose instance return super()._save(name, content_autoclose) + + +class AzureStaticStorage(AzureStorage): # pylint: disable=abstract-method + """Storage class for Static contents""" + + location = "static" + + +class AzureImagesStorage(AzureStorage): # pylint: disable=abstract-method + """Storage class for Image files""" + + location = "images" + overwrite_files = False diff --git a/requirements.txt b/requirements.txt index b63c1f30c..5737d827d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -23,6 +23,7 @@ responses==0.22.0 pytz>=2022.7 boto3==1.26.57 django-storages==1.13.2 +django-storages[azure] django-redis==5.2.0 opentelemetry-api==1.11.1 opentelemetry-exporter-otlp-proto-grpc==1.11.1