Skip to content

fix(profile): stop deleting the shared default banner on upload - #220

Merged
aquie00t merged 1 commit into
mainfrom
fix/default-banner-deleted-on-upload
Aug 26, 2026
Merged

fix(profile): stop deleting the shared default banner on upload#220
aquie00t merged 1 commit into
mainfrom
fix/default-banner-deleted-on-upload

Conversation

@aquie00t

Copy link
Copy Markdown
Collaborator

Problem

https://cdn.developernetwork.net/banners/default_banner.jpe returned 404 — the shared default banner had been deleted from R2.

UpdateBannerUseCase guarded the cleanup of the old banner with oldBannerUrl.includes("banners/default_banner.jpeg"), but the Prisma schema default is banners/default_banner.jpe (note the extension, both in prisma/models/profile.prisma and in 0_init). The guard never matched, so the first banner upload by any user still holding the default called storageService.delete("banners/default_banner.jpe") and removed the shared object for everyone.

UpdateAvatarUseCase had the same shape but its constant happened to match the schema, so avatars were unaffected.

Fix

  • New src/core/domain/constants/default-media.constants.ts exporting DEFAULT_AVATAR_KEY, DEFAULT_BANNER_KEY (both mirroring the schema defaults) and isDefaultMediaKey().
  • isDefaultMediaKey() matches on the file name stem (default_profile / default_banner), so a bare key, a full CDN URL, a cache-busting ?v=1 query string or a different extension all still count as a default asset.
  • Both profile use cases now share that guard instead of each carrying its own literal.
  • Unit tests import the constants from source rather than duplicating them, plus two regression cases on the banner suite: the schema default key, and the default served as a CDN URL with ?v=1.

Verification

  • pnpm vitest run --config vitest.unit.config.ts tests/unit/core/use-cases/profile/ — 55 passed
  • tsc -p tsconfig.build.json --noEmit, pnpm lint, prettier — clean

Ops

The deleted object has already been re-uploaded to R2 at banners/default_banner.jpe. If the 404 was cached at the edge, purge that URL in Cloudflare.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PwzkQ5YGFXSB9jWCZKzX4H

The banner guard compared the stored path against
"banners/default_banner.jpeg", but the Prisma schema default is
"banners/default_banner.jpe". The check never matched, so the first
banner upload by any user still holding the default deleted the shared
default object from R2.

Replace the per-use-case constants with a shared isDefaultMediaKey()
that matches on the file name stem, so a full CDN URL, a cache-busting
query string or a different extension all still count as a default
asset.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PwzkQ5YGFXSB9jWCZKzX4H
@aquie00t
aquie00t merged commit e41f272 into main Aug 26, 2026
10 checks passed
@aquie00t
aquie00t deleted the fix/default-banner-deleted-on-upload branch August 26, 2026 20:19
github-actions Bot pushed a commit that referenced this pull request Aug 26, 2026
## [1.7.4](v1.7.3...v1.7.4) (2026-08-26)

### Bug Fixes

* **profile:** stop deleting the shared default banner on upload ([#220](#220)) ([e41f272](e41f272))
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.7.4 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant