feat: Implement avatar upload system with Cloudflare integration

- Added migration to transition avatar data from CloudflareImageField to ForeignKey structure in UserProfile.
- Fixed UserProfileEvent avatar field to align with new avatar structure.
- Created serializers for social authentication, including connected and available providers.
- Developed request logging middleware for comprehensive request/response logging.
- Updated moderation and parks migrations to remove outdated triggers and adjust foreign key relationships.
- Enhanced rides migrations to ensure proper handling of image uploads and triggers.
- Introduced a test script for the 3-step avatar upload process, ensuring functionality with Cloudflare.
- Documented the fix for avatar upload issues, detailing root cause, implementation, and verification steps.
- Implemented automatic deletion of Cloudflare images upon avatar, park, and ride photo changes or removals.
This commit is contained in:
pacnpal
2025-08-30 21:20:25 -04:00
parent fb6726f89a
commit 9bed782784
75 changed files with 4571 additions and 1962 deletions

41
backend/uv.lock generated
View File

@@ -570,16 +570,18 @@ wheels = [
]
[[package]]
name = "django-cloudflare-images"
version = "0.6.0"
name = "django-cloudflareimages-toolkit"
version = "1.0.7"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "django" },
{ name = "djangorestframework" },
{ name = "pillow" },
{ name = "requests" },
]
sdist = { url = "https://files.pythonhosted.org/packages/f8/f6/5eac43997c2eb797071efb29658df49053be0a873fc23a30033038fd3f7b/django_cloudflare_images-0.6.0.tar.gz", hash = "sha256:bbabb87860a72e0387e8ddb8d71365bf5401997f1b0b8eaad71420fa80ca745b", size = 7296, upload-time = "2024-05-27T06:19:48.319Z" }
sdist = { url = "https://files.pythonhosted.org/packages/5a/e0/f19f5f155c8166e0d2e4df18bdcd8cd18ecf64f6d68c4d9d8ace2158514f/django_cloudflareimages_toolkit-1.0.7.tar.gz", hash = "sha256:620d45cb62f9a4dc290e5afe4d3c7e582345d36111bc0770a06d6ce9fc2528d6", size = 136576, upload-time = "2025-08-30T21:26:39.248Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d6/08/f00887096f4867290eb16b9f21232f9a624beeb6a94fa16550187905613d/django_cloudflare_images-0.6.0-py3-none-any.whl", hash = "sha256:cd7ae17a29784b7f570f8a82cf64fc6ce6539e0193baafdd5532885dc319d18e", size = 6839, upload-time = "2024-05-27T06:19:46.338Z" },
{ url = "https://files.pythonhosted.org/packages/c5/55/25c9d3af623cc9a635c0083ca922471a24f99d5b4ad7d2f2e554df5bb279/django_cloudflareimages_toolkit-1.0.7-py3-none-any.whl", hash = "sha256:5f0ecf12bfa462c19e5fd8936947ad646130f228ddb8e137f3639feb80085372", size = 44062, upload-time = "2025-08-30T21:26:37.616Z" },
]
[[package]]
@@ -641,6 +643,19 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/07/a6/70dcd68537c434ba7cb9277d403c5c829caf04f35baf5eb9458be251e382/django_filter-25.1-py3-none-any.whl", hash = "sha256:4fa48677cf5857b9b1347fed23e355ea792464e0fe07244d1fdfb8a806215b80", size = 94114, upload-time = "2025-02-14T16:30:50.435Z" },
]
[[package]]
name = "django-forwardemail"
version = "1.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "django" },
{ name = "requests" },
]
sdist = { url = "https://files.pythonhosted.org/packages/f5/a1/07011849d802f85422ce36473e4f4255cffc0b12219cb72217f616b787cf/django_forwardemail-1.0.0.tar.gz", hash = "sha256:7cb453a78446f04ba079bcfe5937f34edf1170e33a4378febf31a2561174f3a0", size = 17535, upload-time = "2025-08-30T12:54:34.762Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/4c/a1/fe9d53398de7f80be8e1a85cb64eb9562056638494b4a79a524e9f3e031e/django_forwardemail-1.0.0-py3-none-any.whl", hash = "sha256:29debe5747122c2a29f52682347f72e8caba38bf874f279c36aa49d855e6afc6", size = 16438, upload-time = "2025-08-30T12:54:33.31Z" },
]
[[package]]
name = "django-health-check"
version = "3.20.0"
@@ -695,15 +710,15 @@ wheels = [
[[package]]
name = "django-pghistory"
version = "3.8.0"
version = "3.8.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "django" },
{ name = "django-pgtrigger" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ad/c6/1eaaf356ba52b4276b1cab7690072aea8465d6301790e4b9abb7751f07e9/django_pghistory-3.8.0.tar.gz", hash = "sha256:128c174cf3a5001d669b0e554a1002254cbb1fa43bf79e27822d6a06aed8d5b7", size = 32269, upload-time = "2025-08-17T00:08:47.85Z" }
sdist = { url = "https://files.pythonhosted.org/packages/b0/30/4f6483fe668c0fa05bb7515ace6ba108d5202e65a9838568cc66eb031c67/django_pghistory-3.8.1.tar.gz", hash = "sha256:2590870cad9529c053ca6919cd027c3fb2ce1d0100339badca34898c3e5d3fcc", size = 32233, upload-time = "2025-08-30T19:34:13.119Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e8/11/16ea1e6723c138f4c11d0f21cb86cc547b99df30ee6568da39778d28170a/django_pghistory-3.8.0-py3-none-any.whl", hash = "sha256:32cd4e4c84a6fba035ade904ebc75d07bd3c5837909e59be929325a4783aa1ee", size = 39629, upload-time = "2025-08-17T00:08:46.653Z" },
{ url = "https://files.pythonhosted.org/packages/38/56/9eec32fd9fa72386732f6e8d958bfc2eebc001ab4a7027fa664ff4b01913/django_pghistory-3.8.1-py3-none-any.whl", hash = "sha256:674a5457293b902350a50d2431cf1d496acbef2ed51f7b720e78bcd07c3b01da", size = 39626, upload-time = "2025-08-30T19:34:12.255Z" },
]
[[package]]
@@ -2166,12 +2181,13 @@ dependencies = [
{ name = "django-celery-beat" },
{ name = "django-celery-results" },
{ name = "django-cleanup" },
{ name = "django-cloudflare-images" },
{ name = "django-cloudflareimages-toolkit" },
{ name = "django-cors-headers" },
{ name = "django-debug-toolbar" },
{ name = "django-environ" },
{ name = "django-extensions" },
{ name = "django-filter" },
{ name = "django-forwardemail" },
{ name = "django-health-check" },
{ name = "django-htmx" },
{ name = "django-htmx-autocomplete" },
@@ -2236,12 +2252,13 @@ requires-dist = [
{ name = "django-celery-beat", specifier = ">=2.8.1" },
{ name = "django-celery-results", specifier = ">=2.6.0" },
{ name = "django-cleanup", specifier = ">=8.0.0" },
{ name = "django-cloudflare-images", specifier = ">=0.6.0" },
{ name = "django-cloudflareimages-toolkit", specifier = ">=1.0.6" },
{ name = "django-cors-headers", specifier = ">=4.3.1" },
{ name = "django-debug-toolbar", specifier = ">=4.0.0" },
{ name = "django-environ", specifier = ">=0.12.0" },
{ name = "django-extensions", specifier = ">=4.1" },
{ name = "django-filter", specifier = ">=23.5" },
{ name = "django-forwardemail", specifier = ">=1.0.0" },
{ name = "django-health-check", specifier = ">=3.17.0" },
{ name = "django-htmx", specifier = ">=1.17.2" },
{ name = "django-htmx-autocomplete", specifier = ">=1.0.5" },
@@ -2367,11 +2384,11 @@ wheels = [
[[package]]
name = "typing-extensions"
version = "4.14.1"
version = "4.15.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" }
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" },
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
]
[[package]]